BZOJ4966 : 总统选举
线段树维护每个点的最有可能是答案的数以及它的权重。
合并两个节点的时候,将权重互相抵消,保留较大的那一个。
得到答案后,再在对应权值的Treap中查询出现次数,检查是否真正是答案。
时间复杂度$O(n\log n)$。
#include<cstdio> #include<cstdlib> const int N=500010,M=1100010,BUF=30000000; int n,m,i,a[N],c,d,pos[N],v[M],f[M],V,F;char Buf[BUF],*buf=Buf; inline void read(int&a){for(a=0;*buf<48;buf++);while(*buf>47)a=a*10+*buf++-48;} inline void merge(int a,int b,int c,int d,int&V,int&F){ if(b==d){V=a+c,F=b;return;} if(!b||!d){V=a+c,F=b+d;return;} if(a==c){V=F=0;return;} if(a>c){V=a-c,F=b;return;} V=c-a,F=d; } void build(int x,int a,int b){ if(a==b){ v[x]=1; f[x]=::a[a]; pos[a]=x; return; } int mid=(a+b)>>1; build(x<<1,a,mid),build(x<<1|1,mid+1,b); merge(v[x<<1],f[x<<1],v[x<<1|1],f[x<<1|1],v[x],f[x]); } struct node{ int val,cnt,sum,p;node*l,*r; node(){val=cnt=sum=p=0;l=r=NULL;} inline void up(){sum=cnt+l->sum+r->sum;} }*blank=new(node),pool[1500010],*cur=pool,*T[N]; inline void Rotatel(node*&x){node*y=x->r;x->r=y->l;x->up();y->l=x;y->up();x=y;} inline void Rotater(node*&x){node*y=x->l;x->l=y->r;x->up();y->r=x;y->up();x=y;} void Insert(node*&x,int p){ if(x==blank){ x=cur++;x->val=p;x->l=x->r=blank;x->cnt=x->sum=1;x->p=rand(); return; } x->sum++; if(p==x->val){x->cnt++;return;} if(p<x->val){ Insert(x->l,p); if(x->l->p>x->p)Rotater(x); }else{ Insert(x->r,p); if(x->r->p>x->p)Rotatel(x); } } void Delete(node*&x,int p){ x->sum--; if(p==x->val){x->cnt--;return;} if(p<x->val)Delete(x->l,p);else Delete(x->r,p); } int Ask(node*&x,int p){ if(x==blank)return 0; if(p==x->val)return x->r->sum; if(p<x->val)return x->cnt+x->r->sum+Ask(x->l,p); return Ask(x->r,p); } inline void change(int x){ Delete(T[a[x]],x); Insert(T[a[x]=F],x); f[x=pos[x]]=F; for(x>>=1;x;x>>=1)merge(v[x<<1],f[x<<1],v[x<<1|1],f[x<<1|1],v[x],f[x]); } void ask(int x,int a,int b){ if(c<=a&&b<=d){ merge(V,F,v[x],f[x],V,F); return; } int mid=(a+b)>>1; if(c<=mid)ask(x<<1,a,mid); if(d>mid)ask(x<<1|1,mid+1,b); } inline bool check(int l,int r,int t){ if(!t)return 0; int w=Ask(T[t],l-1)-Ask(T[t],r); return w*2>r-l+1; } int main(){ fread(Buf,1,BUF,stdin);read(n),read(m); blank->l=blank->r=blank; for(i=1;i<=n;i++)T[i]=blank; for(i=1;i<=n;i++)read(a[i]),Insert(T[a[i]],i); build(1,1,n); while(m--){ read(c),read(d); V=F=0; ask(1,1,n); if(!check(c,d,F))F=0; read(c); if(!F)F=c; read(c); while(c--)read(d),change(d); printf("%d\n",F); } if(!check(1,n,f[1]))f[1]=-1; return printf("%d",f[1]),0; }