HDU 3727 Jewel 主席树

来源:互联网 发布:广联达市政预算软件 编辑:程序博客网 时间:2024/06/05 04:26

最近在学主席树。。。反正感觉挺神奇的。。。
我高中想学,但是并没有看懂。可能是他们写的太屎了
kuangbin的板子也不太行。
poj 2104 那题入门,程序是没错
但是太耦合了,变量也有点意义不明。。。
于是我又去找了找。。。发现应该给一个比利比利的链接
qsc菊苣教你主席树啊
这个讲的不错啊 就是p2的时候码力实在太强。。。只能暂停学姿势
然后我又去找最佳实践,,,
但是感觉都有不舒服的地方。。。只能自己瞎编着上了
【知道最佳实践的一定要告诉我啊

Jewel

题意:初始的链为空,需要支持以下四个操作:略。
题解:Query_1 和 Query_3 很明显就是静态第k小,又因为是权值线段树,Query_2 就是前缀和呗。。。
因为数太大啦,再套个离散化,要离散化首先要把操作离线。ok,这样这题就AC啦
这题昨天晚上从开始读到调完正好一小时,而且中间也跟室友吹吹逼啥的
感觉自己码力很有进步啊!然后交上去WA了。。。
当然我其实知道一个WA点,,,answer 没改成 longlong
满怀信心,再交。。。又WA了。。。
刚刚又xjb交了一遍,还是WA
然后去查题解。。。发现我好像有什么地方理解错了。。。

… and the amounts of “Query_1”, “Query_2” and “Query_3” are all less than 35000.

三种询问的数量都不超过35000。。。我似乎理解成和了????
。。。代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N=100001;const int M=35000*3+N;struct chair {    int ls,rs,sum;} T[M*40];struct oper {    int op,x,y,k;} op[M];int root[N],A[N];long long ans[4];int index;int update(int rt,int l,int r,int x){    int newroot=++index;    T[newroot]=T[rt];    T[newroot].sum++;    if (l==r) return newroot;    int m=l+r>>1;    if (x<=m) T[newroot].ls=update(T[newroot].ls,l,m,x);    else T[newroot].rs=update(T[newroot].rs,m+1,r,x);    return newroot;}int query(int x,int y,int l,int r,int k){    if (l==r) return l;    int m=l+r>>1;    int lsz=T[T[y].ls].sum-T[T[x].ls].sum;    if (lsz>=k) {        return query(T[x].ls,T[y].ls,l,m,k);    } else {        return query(T[x].rs,T[y].rs,m+1,r,k-lsz);    }}int getrank(int rt,int l,int r,int L,int R){    if (L<=l&&r<=R) return T[rt].sum;    int m=l+r>>1;    int res=0;    if (L<=m) res+=getrank(T[rt].ls,l,m,L,R);    if (m<R) res+=getrank(T[rt].rs,m+1,r,L,R);    return res;}void case_init(){    index=root[0]=0;    T[0].ls=T[0].rs=T[0].sum=0;    memset(ans,0,sizeof(ans));}int main(){    int cas=0;    int q;    while (scanf("%d",&q)!=EOF) {        int n=0;        case_init();        for (int i=1;i<=q;i++) {            char s[10];            scanf("%s",s);            if (s[0]=='I') {                op[i].op=0;                scanf("%d",&op[i].x);                A[++n]=op[i].x;            } else if (s[6]=='1') {                op[i].op=1;                scanf("%d%d%d",&op[i].x,&op[i].y,&op[i].k);            } else if (s[6]=='2') {                op[i].op=2;                scanf("%d",&op[i].x);            } else if (s[6]=='3') {                op[i].op=3;                scanf("%d",&op[i].k);            }        }        sort(A+1,A+1+n);        int tot=0;        for (int i=1;i<=q;i++) {            if (op[i].op==0) {                tot++;                root[tot]=update(root[tot-1],1,n,lower_bound(A+1,A+1+n,op[i].x)-A);            } else {                long long tmp=0;                if (op[i].op==1)                     tmp=A[query(root[op[i].x-1],root[op[i].y],1,n,op[i].k)];                if (op[i].op==2)                     tmp=getrank(root[tot],1,n,1,lower_bound(A+1,A+1+n,op[i].x)-A);                if (op[i].op==3)                     tmp=A[query(root[0],root[tot],1,n,op[i].k)];                ans[op[i].op]+=tmp;            }        }        printf("Case %d:\n",++cas);        for (int i=1;i<4;i++)            printf("%lld\n",ans[i]);    }}
0 0