【bzoj2223】[Coci 2009]PATULJCI 主席树
题目描述
样例输入
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
样例输出
no
yes 1
no
yes 1
no
yes 2
no
yes 3
题目大意
第一行输入n和lim,为序列数的个数和数的范围(1≤a[i]≤lim)
第二行输入n个数。
第三行输入m,为询问个数。
以下m行输入询问,如题。
对于每个询问,如果存在,输出yes和这个数,否则输出no。
题解
bzoj格式错了。。。
主席树。
对于每个询问,判断它能在左边出现还是能在右边出现,都不能则不存在,能则继续寻找。略水。
不需要离散化。
#include <cstdio> #define N 300001 int root[N] , lp[N << 5] , rp[N << 5] , si[N << 5] , tot; void pushup(int x) { si[x] = si[lp[x]] + si[rp[x]]; } void ins(int x , int &y , int l , int r , int p) { y = ++tot; if(l == r) { si[y] = si[x] + 1; return; } int mid = (l + r) >> 1; if(p <= mid) rp[y] = rp[x] , ins(lp[x] , lp[y] , l , mid , p); else lp[y] = lp[x] , ins(rp[x] , rp[y] , mid + 1 , r , p); pushup(y); } int query(int x , int y , int l , int r , int p) { if(l == r) return l; int mid = (l + r) >> 1; if(si[lp[y]] - si[lp[x]] > p) return query(lp[x] , lp[y] , l , mid , p); if(si[rp[y]] - si[rp[x]] > p) return query(rp[x] , rp[y] , mid + 1 , r , p); return 0; } int main() { int n , lim , m , i , x , y , t; scanf("%d%d" , &n , &lim); for(i = 1 ; i <= n ; i ++ ) { scanf("%d" , &x); ins(root[i - 1] , root[i] , 1 , lim , x); } scanf("%d" , &m); while(m -- ) { scanf("%d%d" , &x , &y); t = query(root[x - 1] , root[y] , 1 , lim , (y - x + 1) >> 1); if(t) printf("yes %d\n" , t); else printf("no\n"); } return 0; }