#bzoj1846
来源:互联网 发布:js清除浏览器缓存数据 编辑:程序博客网 时间:2024/06/08 14:54
问题 A(1846): 【山东省选】郁闷的小J
时间限制: 4 Sec 内存限制: 512 MB题目描述
小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架。虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的危险,这也正是他所郁闷的。
具体说来,书架由N个书位组成,编号从1到N。每个书位放着一本书,每本书有一个特定的编码。
小J的工作有两类:
- 图书馆经常购置新书,而书架任意时刻都是满的,所以只得将某位置的书拿掉并换成新购的书。
- 小J需要回答顾客的查询,顾客会询问某一段连续的书位中某一特定编码的书有多少本。
例如,共5个书位,开始时书位上的书编码为1,2,3,4,5
一位顾客询问书位1到书位3中编码为“2”的书共多少本,得到的回答为:1
一位顾客询问书位1到书位3中编码为“1”的书共多少本,得到的回答为:1
此时,图书馆购进一本编码为“1”的书,并将它放到2号书位。
一位顾客询问书位1到书位3中编码为“2”的书共多少本,得到的回答为:0
一位顾客询问书位1到书位3中编码为“1”的书共多少本,得到的回答为:2
……
你的任务是写一个程序来回答每个顾客的询问。
输入
第一行两个整数N,M,表示一共N个书位,M个操作。
接下来一行共N个整数数A1,A2…AN,Ai表示开始时位置i上的书的编码。
接下来M行,每行表示一次操作,每行开头一个字符
若字符为‘C’,表示图书馆购进新书,后接两个整数A(1<=A<=N),P,表示这本书被放在位置A上,以及这本书的编码为P。
若字符为‘Q’,表示一个顾客的查询,后接三个整数A,B,K(1<=A<=B<=N),表示查询从第A书位到第B书位(包含A和B)中编码为K的书共多少本。
(1<=N,M<=100000,所有出现的书的编码为不大于2147483647的正数。)
输出
对每一个顾客的查询,输出一个整数,表示顾客所要查询的结果。
样例输入
5 51 2 3 4 5Q 1 3 2Q 1 3 1C 2 1Q 1 3 2Q 1 3 1
样例输出
1102
朴素地强行直接按照位置来做平衡树是会超时的(后面会给出我的超时代码,可以先拿去交交看)这里给出两种做法(正解):
法一:
将询问全部读入,离散化书的编号,
然后按照每书的种类不同,每种书建一棵树,树的内容为此种书摆放的位置。
每次C操作先删去原来位置上那种书的树中节点(数组持续更新记录位置上是哪种书),再在新书的树中加入节点
每次Q操作在书的树中累计区间数。
法二:
定义平衡树的顺序为:
1,书的编号种类。2,书的位置(这个注意看结构体里面的重载就比较清晰了)
按正常建树,
每次C操作把原来那个点删除后插入新点
每次Q操作就像查询排名一样后面的排名-前面的排名(注意是在之前的大小定义下)
想不通就想想这棵树的中序遍历,同一类书在中序里是挨在一起的说。
给出两种代码:
Code:
法一:
#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std; const int Max = 100005;const int INF = 0x3f3f3f3f; struct Pro{ int l, r, p;}Ask[Max];struct node{ int num, sum; int lc, rc, h;}Tr[Max << 1]; int cnt, Pre, Suc;int Root[Max], B[Max], S[Max << 1], Shelf[Max]; void getint(int & num){ char c; int flg = 1; num = 0; while((c = getchar()) < '0' || c > '9') if(c == '-') flg = -1; while(c >= '0' && c <= '9') { num = num * 10 + c - 48; c = getchar();} num *= flg;} int max(int a, int b){ return a < b ? b : a;}int min(int a, int b){ return a < b ? a : b;} void pushup(int & r){ Tr[r].sum = Tr[Tr[r].lc].sum + Tr[Tr[r].rc].sum + 1; Tr[r].h = max(Tr[Tr[r].lc].h, Tr[Tr[r].rc].h) + 1;} int zig(int r){ int t = Tr[r].lc; Tr[r].lc = Tr[t].rc, Tr[t].rc = r; pushup(r), pushup(t); return t;} int zag(int r){ int t = Tr[r].rc; Tr[r].rc = Tr[t].lc, Tr[t].lc = r; pushup(r), pushup(t); return t;} int zigzag(int r){ Tr[r].rc = zig(Tr[r].rc); return zag(r);} int zagzig(int r){ Tr[r].lc = zag(Tr[r].lc); return zig(r);} void maintain(int & r){ if(Tr[Tr[r].lc].h == Tr[Tr[r].rc].h + 2){ int t = Tr[r].lc; if(Tr[Tr[t].lc].h == Tr[Tr[r].rc].h + 1) r = zig(r); else if(Tr[Tr[t].rc].h == Tr[Tr[r].rc].h + 1) r = zagzig(r); } else if(Tr[Tr[r].rc].h == Tr[Tr[r].lc].h + 2){ int t = Tr[r].rc; if(Tr[Tr[t].rc].h == Tr[Tr[r].lc].h + 1) r = zag(r); else if(Tr[Tr[t].lc].h == Tr[Tr[r].lc].h + 1) r = zigzag(r); } pushup(r);} void Insert(int & r, int val){ if(! r){ r = ++ cnt; Tr[r].num = val; Tr[r].h = Tr[r].sum = 1; return ; } if(val < Tr[r].num) Insert(Tr[r].lc, val); else Insert(Tr[r].rc, val); maintain(r);} int Dele(int & r, int val){ int tx; if(Tr[r].num == val || (val < Tr[r].num && ! Tr[r].lc) || ( val > Tr[r].num && ! Tr[r].rc)){ if(! Tr[r].lc || ! Tr[r].rc){ tx = Tr[r].num; r = Tr[r].lc + Tr[r].rc; return tx; } else Tr[r].num = Dele(Tr[r].lc, val); } else { if(val < Tr[r].num) tx = Dele(Tr[r].lc, val); else tx = Dele(Tr[r].rc, val); } maintain(r); return tx;} int Search(int &r, int pos){ if(! r) return 0; int sum = 0; if(Tr[r].num <= pos){ if(Tr[r].lc) sum += Tr[Tr[r].lc].sum; ++ sum; } if(Tr[r].num <= pos) sum += Search(Tr[r].rc, pos); else sum += Search(Tr[r].lc, pos); return sum;} int main(){ int N, M, tot; getint(N), getint(M); for(int i = 1; i <= N; ++ i){ getint(B[i]); S[i] = B[i]; } char ord[5]; tot = N; for(int i = 1; i <= M; ++ i){ scanf("%s", ord); if(ord[0] == 'Q'){ getint(Ask[i].l), getint(Ask[i].r); getint(Ask[i].p); S[++ tot] = Ask[i].p; } else { getint(Ask[i].l), getint(Ask[i].p); Ask[i].r = -1; } } sort(S + 1, S + tot + 1); int len = unique(S + 1, S + tot + 1) - S; int tmp; for(int i = 1; i <= N; ++ i){ tmp = lower_bound(S + 1, S + 1 + len, B[i]) - S; Shelf[i] = tmp; Insert(Root[tmp], i); } for(int i = 1; i <= M; ++ i){ if(Ask[i].r != -1){ tmp = lower_bound(S + 1, S + 1 + len, Ask[i].p) - S; printf("%d\n", Search(Root[tmp], Ask[i].r) - Search(Root[tmp], Ask[i].l - 1)); } else { tmp = lower_bound(S + 1, S + 1 + len, Ask[i].p) - S; Dele(Root[Shelf[Ask[i].l]], Ask[i].l); Shelf[Ask[i].l] = tmp; Insert(Root[tmp], Ask[i].l); } } return 0;}
法二:
#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;const int Max = 100005;const int INF = 0x3f3f3f3f;struct bk{ int biao, pos; bk(){} bk(int a, int b){biao = a, pos = b;}bool operator <(const bk & X)const{if(biao == X.biao)return pos < X.pos;return biao < X.biao;}bool operator == (const bk & X)const{return biao == X.biao && pos == X.pos;}};struct node{ bk num; int lc, rc, h, sum;}Tr[Max << 1];int cnt;int Shelf[Max];void getint(int & num){ char c; int flg = 1; num = 0; while((c = getchar()) < '0' || c > '9') if(c == '-') flg = -1; while(c >= '0' && c <= '9') { num = num * 10 + c - 48; c = getchar();} num *= flg;}int max(int a, int b){ return a < b ? b : a;}int min(int a, int b){ return a < b ? a : b;}void pushup(int & r){ Tr[r].h = max(Tr[Tr[r].lc].h, Tr[Tr[r].rc].h) + 1;Tr[r].sum = Tr[Tr[r].lc].sum + Tr[Tr[r].rc].sum + 1;}int zig(int r){ int t = Tr[r].lc; Tr[r].lc = Tr[t].rc, Tr[t].rc = r; pushup(r), pushup(t); return t;}int zag(int r){ int t = Tr[r].rc; Tr[r].rc = Tr[t].lc, Tr[t].lc = r; pushup(r), pushup(t); return t;}int zigzag(int r){ Tr[r].rc = zig(Tr[r].rc); return zag(r);}int zagzig(int r){ Tr[r].lc = zag(Tr[r].lc); return zig(r);}void maintain(int & r){ if(Tr[Tr[r].lc].h == Tr[Tr[r].rc].h + 2){ int t = Tr[r].lc; if(Tr[Tr[t].lc].h == Tr[Tr[r].rc].h + 1) r = zig(r); else if(Tr[Tr[t].rc].h == Tr[Tr[r].rc].h + 1) r = zagzig(r); } else if(Tr[Tr[r].rc].h == Tr[Tr[r].lc].h + 2){ int t = Tr[r].rc; if(Tr[Tr[t].rc].h == Tr[Tr[r].lc].h + 1) r = zag(r); else if(Tr[Tr[t].lc].h == Tr[Tr[r].lc].h + 1) r = zigzag(r); } pushup(r);}void Insert(int & r, bk val){ if(! r){ r = ++ cnt; Tr[r].num = val; Tr[r].h = Tr[r].sum = 1; return ; } if(val < Tr[r].num) Insert(Tr[r].lc, val); else Insert(Tr[r].rc, val); maintain(r);}bk Dele(int & r, bk val){ bk tx; if(Tr[r].num == val || (val < Tr[r].num && ! Tr[r].lc) || (Tr[r].num < val && ! Tr[r].rc)){ if(! Tr[r].lc || ! Tr[r].rc){ tx = Tr[r].num; r = Tr[r].lc + Tr[r].rc; return tx; } else Tr[r].num = Dele(Tr[r].lc, val); } else { if(val < Tr[r].num) tx = Dele(Tr[r].lc, val); else tx = Dele(Tr[r].rc, val); } maintain(r); return tx;}int Query(int r, bk val){if(! r)return 0;if(Tr[r].num < val)return Tr[Tr[r].lc].sum + 1 + Query(Tr[r].rc, val);return Query(Tr[r].lc, val);}int main(){ int R = 0, N, M, A, B, K; getint(N), getint(M); for(int i = 1; i <= N; ++ i){ getint(Shelf[i]); Insert(R, bk(Shelf[i], i)); } char ord[10]; while(M --){ scanf("%s", ord); switch(ord[0]){ case 'Q':{ getint(A), getint(B), getint(K); printf("%d\n", Query(R, bk(K, B)) - Query(R, bk(K, A)) + (Shelf[B] == K)); break; } case 'C':{ getint(A), getint(K); Dele(R, bk(Shelf[A], A));Shelf[A] = K; Insert(R, bk(K, A)); break; } } } return 0;}
超时的朴素代码。。。。如下(留做个纪念吧,还是打了一小会儿呢):
#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;const int Max = 200005;const int INF = 0x3f3f3f3f;struct bk{ int biao, pos; bk(){} bk(int a, int b){biao = a, pos = b;}};struct node{ bk num; int lc, rc, h;}Tr[Max];int cnt, Pre, Suc;void getint(int & num){ char c; int flg = 1; num = 0; while((c = getchar()) < '0' || c > '9') if(c == '-') flg = -1; while(c >= '0' && c <= '9') { num = num * 10 + c - 48; c = getchar();} num *= flg;}int max(int a, int b){ return a < b ? b : a;}int min(int a, int b){ return a < b ? a : b;}void pushup(int & r){ Tr[r].h = max(Tr[Tr[r].lc].h, Tr[Tr[r].rc].h) + 1;}int zig(int r){ int t = Tr[r].lc; Tr[r].lc = Tr[t].rc, Tr[t].rc = r; pushup(r), pushup(t); return t;}int zag(int r){ int t = Tr[r].rc; Tr[r].rc = Tr[t].lc, Tr[t].lc = r; pushup(r), pushup(t); return t;}int zigzag(int r){ Tr[r].rc = zig(Tr[r].rc); return zag(r);}int zagzig(int r){ Tr[r].lc = zag(Tr[r].lc); return zig(r);}void maintain(int & r){ if(Tr[Tr[r].lc].h == Tr[Tr[r].rc].h + 2){ int t = Tr[r].lc; if(Tr[Tr[t].lc].h == Tr[Tr[r].rc].h + 1) r = zig(r); else if(Tr[Tr[t].rc].h == Tr[Tr[r].rc].h + 1) r = zagzig(r); } else if(Tr[Tr[r].rc].h == Tr[Tr[r].lc].h + 2){ int t = Tr[r].rc; if(Tr[Tr[t].rc].h == Tr[Tr[r].lc].h + 1) r = zag(r); else if(Tr[Tr[t].lc].h == Tr[Tr[r].lc].h + 1) r = zigzag(r); } pushup(r);}void Insert(int & r, bk val){ if(! r){ r = ++ cnt; Tr[r].num = val; Tr[r].h = 1; return ; } if(val.pos < Tr[r].num.pos) Insert(Tr[r].lc, val); else Insert(Tr[r].rc, val); maintain(r);}bk Dele(int & r, int pos){ bk tx; if(Tr[r].num.pos == pos || (pos < Tr[r].num.pos && ! Tr[r].lc) || (pos > Tr[r].num.pos && ! Tr[r].rc)){ if(! Tr[r].lc || ! Tr[r].rc){ tx = Tr[r].num; r = Tr[r].lc + Tr[r].rc; return tx; } else Tr[r].num = Dele(Tr[r].lc, pos); } else { if(pos < Tr[r].num.pos) tx = Dele(Tr[r].lc, pos); else tx = Dele(Tr[r].rc, pos); } maintain(r); return tx;}int Query(int R, int l, int r, int k){ if(! R) return 0; if(Tr[R].num.pos < l) return Query(Tr[R].rc, l, r, k); if(Tr[R].num.pos > r) return Query(Tr[R].lc, l, r, k); bool flg = 0; if(Tr[R].num.biao == k) flg = 1; return flg + Query(Tr[R].lc, l, r, k) + Query(Tr[R].rc, l, r, k);}int main(){ int R = 0, N, M, x, A, B, K; getint(N), getint(M); for(int i = 1; i <= N; ++ i){ getint(x); Insert(R, bk(x, i)); } char ord[10]; while(M --){ scanf("%s", ord); switch(ord[0]){ case 'Q':{ getint(A), getint(B), getint(K); printf("%d\n", Query(R, A, B, K)); break; } case 'C':{ getint(A), getint(K); Dele(R, A); Insert(R, bk(K, A)); break; } } } return 0;}
- #bzoj1846
- 关于Linearlayout里weight与子布局的wrap content
- php模拟长连接
- VS2010的编码经验
- tomcat大量time wait问题
- Spring Data JPA入门
- #bzoj1846
- 破解防拷贝脚本
- C 预处理器和C库
- MyBatis的知识点
- linux查看日志
- 欢迎使用CSDN-markdown编辑器
- pycharm + virtualenv搭建python2.7 和python 3.0的多python运行环境
- 解决Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?
- ZOJ-3329 One Person Game(期望dp)