主席树||可持久化线段树||BZOJ 3524: [Poi2014]Couriers||BZOJ 2223: [Coci 2009]PATULJCI||Luogu P3567 [POI2014]KUR

题目:[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

 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

上一篇:虚拟机与容器的混合管理实践


下一篇:Android 实现双Launcher的无缝切换,安卓开发面试书籍