【BZOJ-2223】PATULJCI 可持久化线段树
2223: [Coci 2009]PATULJCI
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 728 Solved: 292
[Submit][Status][Discuss]
Description
Input
Output
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
Sample Input
no
yes 1
no
yes 1
no
yes 2
no
yes 3
yes 1
no
yes 1
no
yes 2
no
yes 3
Sample Output
HINT
Notice:输入第二个整数是序列中权值的范围Lim,即1<=ai(1<=i<=n)<=Lim。
1<=Lim<=10000
Source
Solution
题面应该是出问题了
方法很简单,主席树的建法,不过询问的是次数,裸题
Code
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-')f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } int n,m,lim; #define maxn 500001 int sum[maxn*20],ll[maxn*20],rr[maxn*20],root[maxn<<2],sz; void insert(int l,int r,int &now,int fat,int val) { now=++sz; sum[now]=sum[fat]+1; if (l==r) return; ll[now]=ll[fat],rr[now]=rr[fat]; int mid=(l+r)>>1; if (val<=mid) insert(l,mid,ll[now],ll[fat],val); else insert(mid+1,r,rr[now],rr[fat],val); } int query(int l,int r,int L,int R) { int LL=root[L-1],RR=root[R]; while (l!=r) { int mid=(l+r)>>1; if (sum[RR]-sum[LL]<=(R-L+1)/2) return 0; if (sum[ll[RR]]-sum[ll[LL]]>(R-L+1)/2) LL= ll[LL],RR=ll[RR],r=mid; else if (sum[rr[RR]]-sum[rr[LL]]>(R-L+1)/2) LL=rr[LL],RR=rr[RR],l=mid+1; else return 0; } return l; } int main() { n=read();lim=read(); for (int a,i=1; i<=n; i++) a=read(),insert(1,lim,root[i],root[i-1],a); m=read(); for (int l,r,i=1; i<=m; i++) { l=read(),r=read(); if (l>r) swap(l,r); int ans=query(1,lim,l,r); if (!ans) puts("no"); else printf("yes %d\n",ans); } return 0; }
心态爆炸了,做做水题
——It's a lonely path. Don't make it any lonelier than it has to be.