[bzoj2653]middle
2016-03-17 08:23
323 查看
2653: middle
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 984 Solved: 571
[Submit][Status][Discuss]
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]。
输入保证满足条件。
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
HINT
0:n,Q<=100
1,…,5:n<=2000
0,…,19:n<=20000,Q<=25000
题目中要求的是中位数,中位数这个东西看上去很像二分对吧,那对于一个询问,首先二分答案。怎样判断答案是否正确呢?
假如当前二分的数是k,那么将n个数中所有>=k的全赋成1,< k的赋成-1,这样就是相当于求一段最大的连续字段和,看看能否>=0。直到找到一个k,使得k的时候>=0,k+1的时候<0,那么这个k就是我们要的答案。
但是对于每一个二分的值,不能暴力修改线段树中的每一个元素。所以我们就需要用到主席树。
首先将输入的数排序,我们将主席树的外层当做数的权值,内层是数的序号。开始的时候建议可完整的数,所有节点都是1,。然后将排完序的数组依次添加到主席树中去.。这样查询一个数k的时候,只需要找到对应的root[k]中去找就行了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define mid (L+R)/2 const int N=20010; const int M=800010; struct S{int No,v;}a ; int n,m,siz,q[5],root ,l[M],r[M],sum[M],lmax[M],rmax[M]; inline bool cmp(S x,S y){return x.v<y.v;} inline void update(int k){ sum[k]=sum[l[k]]+sum[r[k]]; lmax[k]=max(lmax[l[k]],sum[l[k]]+lmax[r[k]]); rmax[k]=max(rmax[r[k]],sum[r[k]]+rmax[l[k]]); } inline void build(int L,int R,int &k){ k=++siz; if(L==R){ lmax[k]=rmax[k]=sum[k]=1; return ; } build(L,mid,l[k]); build(mid+1,R,r[k]); update(k); } inline void insert(int L,int R,int x,int &y,int z,int value){ y=++siz; if(L==R){ lmax[y]=rmax[y]=sum[y]=value; return ; } l[y]=l[x];r[y]=r[x]; if(z<=mid) insert(L,mid,l[x],l[y],z,value); else insert(mid+1,R,r[x],r[y],z,value); update(y); } inline int query_sum(int L,int R,int k,int x,int y){ int tot=0; if(x<=L&&y>=R) return sum[k]; if(x<=mid) tot+=query_sum(L,mid,l[k],x,y); if(y>mid) tot+=query_sum(mid+1,R,r[k],x,y); return tot; } inline int query_lmax(int L,int R,int k,int x,int y){ if(x==L&&y==R) return lmax[k]; if(x>mid) return query_lmax(mid+1,R,r[k],x,y); else if(y<=mid) return query_lmax(L,mid,l[k],x,y); else return max(query_lmax(L,mid,l[k],x,mid),query_sum(L,mid,l[k],x,mid)+query_lmax(mid+1,R,r[k],mid+1,y)); } inline int query_rmax(int L,int R,int k,int x,int y){ if(x==L&&y==R) return rmax[k]; if(x>mid) return query_rmax(mid+1,R,r[k],x,y); else if(y<=mid) return query_rmax(L,mid,l[k],x,y); else return max(query_rmax(mid+1,R,r[k],mid+1,y),query_sum(mid+1,R,r[k],mid+1,y)+query_rmax(L,mid,l[k],x,mid)); } inline bool check(int x){ int tot=0; tot=query_sum(1,n,root[x],q[2],q[3]); //if(x==8) cout<<tot<<"~"<<endl; if(q[1]<=q[2]-1) tot+=max(0,query_rmax(1,n,root[x],q[1],q[2]-1)); //if(x==8) cout<<tot<<' '<<q[3]<<' '<<q[4]<<"~~"<<endl; if(q[3]+1<=q[4]) tot+=max(0,query_lmax(1,n,root[x],q[3]+1,q[4])); //cout<<x<<' '<<tot<<endl; return tot>=0; } int main(){ //freopen("input.in","r",stdin); int i,j,ans=0; scanf("%d",&n); for(i=1;i<=n;++i){ a[i].No=i; scanf("%d",&a[i].v); } sort(a+1,a+n+1,cmp); //for(i=1;i<=n;++i) cout<<a[i].v<<' '; //cout<<endl; build(1,n,root[1]); for(i=2;i<=n;++i) insert(1,n,root[i-1],root[i],a[i-1].No,-1); /*for(i=1;i<=n;++i) cout<<sum[root[i]]<<' '; while(1);*/ scanf("%d",&m); while(m--){ for(i=1;i<=4;++i) scanf("%d",&q[i]),q[i]=(q[i]+ans)%n+1; sort(q+1,q+5); //for(i=1;i<=4;++i) cout<<q[i]<<' '; //cout<<endl; //while(1); int L=1,R=n+1;ans=1; //cout<<m<<"~"<<endl; //if(m==0) cout<<check(5)<<"~"<<endl; while(L<R){ //cout<<L<<' '<<R<<' '<<mid<<"!"<<endl; if(check(mid)) ans=max(ans,mid),L=mid+1; else R=mid; } ans=a[ans].v; printf("%d\n",ans); } }
相关文章推荐
- 第三周项目三-输出星号图
- hdu3267 Graph Game 完全极大极小搜索+连通性剪枝+缩点
- 项目2:本月有几天?
- HTTP 请求方式: GET和POST的比较
- 第三周项目4——(3)年龄几何
- fullpage.js 结合固定导航栏—实现定位导航栏
- 基于14.04 ubuntu 配置 eclipse 为opencv 第二篇
- 深入浅出Spring之第三章AOP
- Android中fragment_main.xml文件里的组件获取的问题
- 第四周上机实践项目 项目3--随机函数应用游戏(2)小学算数能力测试系统
- 快速查询图片及参数的意义
- keil5的安装+工程的创建
- Activity生命周期
- JQuery控制DIV的选取
- Spring+SpringMVC+Mybatis整合
- Aizu - 0118(深搜)
- 哈夫曼树
- 哈夫曼树
- 子线程Handler.sendMessage 报错:Attempt to invoke virtual method 'boolean android.os.Handler.sendMessage
- 20.5 语音合成(百度2016年2月29日发布的tts引擎)