• BZOJ2653: middle


    BZOJ2653: middle

    Description

    一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整。
    给你一个长度为n的序列s。
    回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数。
    其中a<b<c<d。
    位置也从0开始标号。
    我会使用一些方式强制你在线。

    Input

    第一行序列长度n。
    接下来n行按顺序给出a中的数。
    接下来一行Q。
    然后Q行每行a,b,c,d,我们令上个询问的答案是x(如果这是第一个询问则x=0)。
    令数组q={(a+x)%n,(b+x)%n,(c+x)%n,(d+x)%n}。
    将q从小到大排序之后,令真正的要询问的a=q[0],b=q[1],c=q[2],d=q[3]。  
    输入保证满足条件。
    第一行所谓“排过序”指的是从小到大排序!
    n<=20000,Q<=25000

    Output

    Q行依次给出询问的答案。

    Sample Input

    5
    170337785
    271451044
    22430280
    969056313
    206452321
    3
    3 1 0 2
    2 3 1 4
    3 1 4 0

    Sample Output

    271451044
    271451044
    969056313

    题解Here!

    第一眼看去好不可做啊。。。
    考虑二分答案。
    假设我们二分出一个值$mid$,把小于它的数设为$-1$,大于它的数设为$1$。
    然后对$[a,b]$求最大后缀和,对$[c,d]$求最大前缀和,对$[b+1,c-1]$求和。
    如果和大于等于$0$,说明这个数还可以再大一些,否则只能小一些。
    至于那个$1,-1$怎么改。。。搞一个主席树就好。
    附代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define MAXN 20010
    #define MAX 999999999
    using namespace std;
    int n,m;
    int val[MAXN],id[MAXN];
    int size=0,root[MAXN];
    struct Chairman_Tree{
    	int lsum,rsum,sum,lson,rson;
    	Chairman_Tree(){
    		lsum=rsum=-MAX;
    		sum=0;
    	}
    	friend Chairman_Tree operator +(const Chairman_Tree p,const Chairman_Tree q){
    		Chairman_Tree x;
    		x.lsum=max(p.lsum,p.sum+q.lsum);
    		x.rsum=max(q.rsum,p.rsum+q.sum);
    		x.sum=p.sum+q.sum;
    		return x;
    	}
    }a[MAXN*22];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline bool cmp(const int &p,const int &q){
    	return val[p]<val[q];
    }
    inline void pushup(int rt){
    	a[rt].lsum=max(a[a[rt].lson].lsum,a[a[rt].lson].sum+a[a[rt].rson].lsum);
    	a[rt].rsum=max(a[a[rt].rson].rsum,a[a[rt].lson].rsum+a[a[rt].rson].sum);
    	a[rt].sum=a[a[rt].lson].sum+a[a[rt].rson].sum;
    }
    int buildtree(int l,int r){
    	int rt=++size;
    	if(l==r){
    		a[rt].sum=a[rt].lsum=a[rt].rsum=r-l+1;
    		return rt;
    	}
    	int mid=l+r>>1;
    	a[rt].lson=buildtree(l,mid);
    	a[rt].rson=buildtree(mid+1,r);
    	pushup(rt);
    	return rt;
    }
    void insert(int k,int l,int r,int &rt){
    	a[++size]=a[rt];rt=size;
    	if(l==r){
    		a[rt].sum=a[rt].lsum=a[rt].rsum=-1;
    		return;
    	}
    	int mid=l+r>>1;
    	if(k<=mid)insert(k,l,mid,a[rt].lson);
    	else insert(k,mid+1,r,a[rt].rson);
    	pushup(rt);
    }
    Chairman_Tree query(int lside,int rside,int l,int r,int rt){
    	if(lside<=l&&r<=rside)return a[rt];
    	int mid=l+r>>1;
    	Chairman_Tree lson,rson;
    	if(lside<=mid)lson=query(lside,rside,l,mid,a[rt].lson);
    	if(mid<rside)rson=query(lside,rside,mid+1,r,a[rt].rson);
    	return (lson+rson);
    }
    inline bool check(int l1,int r1,int l2,int r2,int x){
    	int s=0;
    	Chairman_Tree ans;
    	if(r1+1<=l2-1){
    		ans=query(r1+1,l2-1,1,n,root[x]);
    		s+=ans.sum;
    	}
    	ans=query(l1,r1,1,n,root[x]);
    	s+=ans.rsum;
    	ans=query(l2,r2,1,n,root[x]);
    	s+=ans.lsum;
    	return (s>=0);
    }
    int solve(int l1,int r1,int l2,int r2){
    	int l=1,r=n,ans;
    	while(l<=r){
    		int mid=l+r>>1;
    		if(check(l1,r1,l2,r2,mid)){
    			ans=val[id[mid]];
    			l=mid+1;
    		}
    		else r=mid-1;
    	}
    	return ans;
    }
    void work(){
    	int l1,r1,l2,r2,last=0,q[4];
    	while(m--){
    		for(int i=0;i<4;i++)q[i]=(read()+last)%n;
    		sort(q,q+4);
    		l1=q[0]+1;r1=q[1]+1;l2=q[2]+1;r2=q[3]+1;
    		last=solve(l1,r1,l2,r2);
    		printf("%d
    ",last);
    	}
    }
    void init(){
    	n=read();
    	for(int i=1;i<=n;i++){
    		val[i]=read();
    		id[i]=i;
    	}
    	sort(id+1,id+n+1,cmp);
    	root[1]=buildtree(1,n);
    	for(int i=2;i<=n;i++){
    		root[i]=root[i-1];
    		insert(id[i-1],1,n,root[i]);
    	}
    	m=read();
    }
    int main(){
    	init();
    	work();
    	return 0;
    }
    
  • 相关阅读:
    PowerTalk第一个版本儿控件
    PowerTalk第二个版本,支持(Msn回复信息)
    自然语言处理著作或期刊名称
    自然语言处理(NLP)网上资源整理 (转)
    TFIDF
    计算机科学及工程
    自然语言处理与计算语言学书籍汇总之一:国外书籍
    UVa 10696 f91
    缓存
    操作必须使用一个可更新的查询(转)
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/10632109.html
Copyright © 2020-2023  润新知