主席树||可持久化线段树||BZOJ 3524: [Poi2014]Couriers||BZOJ 2223: [Coci 2009]PATULJCI||Luogu P3567 [POI2014]KUR-Couriers
题解:
要求出现次数大于(R-L+1)/2的数,这样的数最多只有一个。我们对序列做主席树,每个节点记录出现的次数和(sum)。(这里忽略版本差值问题)对于一个节点,如果左儿子的sum小于等于(R-L+1)/2,则答案不可能在左儿子中;右儿子同理。然后对有可能的儿子递归寻找答案,如果左右儿子都不可能,则不存在答案。
代码:
BZOJ 3524:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 inline int rd(){ 6 int x=0,f=1;char c=getchar(); 7 while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} 8 while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} 9 return f*x; 10 } 11 const int maxn=(5e5)+50,maxm=maxn; 12 int N,M,L,R,root[maxn],num_treenode=0,A; 13 struct Tree{ 14 int l,r,sum,ls,rs; 15 }t[(maxn<<2)+maxn*20]; 16 inline void Build(int x,int l,int r){ 17 t[x].l=l;t[x].r=r;int mid=(l+r)>>1; 18 if(l==r)return; 19 Build(t[x].ls=++num_treenode,l,mid);Build(t[x].rs=++num_treenode,mid+1,r); 20 return; 21 } 22 inline void Update(int u,int x,int q){ 23 int l=t[u].l,r=t[u].r,mid=(l+r)>>1; 24 t[x].l=l;t[x].r=r; 25 if(l==r&&l==q){ 26 t[x].sum=t[u].sum+1; 27 return; 28 } 29 if(q<=mid){ 30 t[x].rs=t[u].rs; 31 Update(t[u].ls,t[x].ls=++num_treenode,q); 32 } 33 else { 34 t[x].ls=t[u].ls; 35 Update(t[u].rs,t[x].rs=++num_treenode,q); 36 } 37 t[x].sum=t[t[x].ls].sum+t[t[x].rs].sum; 38 return; 39 } 40 inline int Query(int u,int x,int z){ 41 int l=t[u].l,r=t[u].r; 42 if(l==r)return l; 43 if(t[t[x].ls].sum-t[t[u].ls].sum>z)return Query(t[u].ls,t[x].ls,z); 44 if(t[t[x].rs].sum-t[t[u].rs].sum>z)return Query(t[u].rs,t[x].rs,z); 45 return 0; 46 } 47 int main(){ 48 N=rd();M=rd(); 49 Build(root[0]=++num_treenode,1,N); 50 for(int i=1;i<=N;i++){ 51 A=rd(); 52 Update(root[i-1],root[i]=++num_treenode,A); 53 } 54 while(M--){ 55 L=rd();R=rd(); 56 printf("%d\n",Query(root[L-1],root[R],(R-L+1)>>1)); 57 } 58 return 0; 59 }
BZOJ 2223:
这道题的样例很坑,我整理了一下:
10 3 1 2 1 2 1 2 3 2 3 3 8 1 2 1 3 1 4 1 5 2 5 2 6 6 9 7 10
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 inline int rd(){ 6 int x=0,f=1;char c=getchar(); 7 while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} 8 while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} 9 return f*x; 10 } 11 const int maxn=(3e5)+50,maxm=10050; 12 int N,M,L,R,root[maxn],num_treenode=0,A,ans,Lim; 13 struct Tree{ 14 int l,r,sum,ls,rs; 15 }t[(maxn<<2)+maxn*20]; 16 inline void Build(int x,int l,int r){ 17 t[x].l=l;t[x].r=r;int mid=(l+r)>>1; 18 if(l==r)return; 19 Build(t[x].ls=++num_treenode,l,mid);Build(t[x].rs=++num_treenode,mid+1,r); 20 return; 21 } 22 inline void Update(int u,int x,int q){ 23 int l=t[u].l,r=t[u].r,mid=(l+r)>>1; 24 t[x].l=l;t[x].r=r; 25 if(l==r&&l==q){ 26 t[x].sum=t[u].sum+1; 27 return; 28 } 29 if(q<=mid){ 30 t[x].rs=t[u].rs; 31 Update(t[u].ls,t[x].ls=++num_treenode,q); 32 } 33 else { 34 t[x].ls=t[u].ls; 35 Update(t[u].rs,t[x].rs=++num_treenode,q); 36 } 37 t[x].sum=t[t[x].ls].sum+t[t[x].rs].sum; 38 return; 39 } 40 inline int Query(int u,int x,int z){ 41 int l=t[u].l,r=t[u].r; 42 if(l==r)return l; 43 if(t[t[x].ls].sum-t[t[u].ls].sum>z)return Query(t[u].ls,t[x].ls,z); 44 if(t[t[x].rs].sum-t[t[u].rs].sum>z)return Query(t[u].rs,t[x].rs,z); 45 return 0; 46 } 47 int main(){ 48 N=rd();Lim=rd(); 49 Build(root[0]=++num_treenode,1,Lim); 50 for(int i=1;i<=N;i++){ 51 A=rd(); 52 Update(root[i-1],root[i]=++num_treenode,A); 53 } 54 M=rd(); 55 while(M--){ 56 L=rd();R=rd(); 57 if(L>R){ 58 printf("no\n"); 59 continue; 60 } 61 ans=Query(root[L-1],root[R],(R-L+1)>>1); 62 if(ans==0)printf("no\n");else printf("yes %d\n",ans); 63 } 64 return 0; 65 }
By:AlenaNuna