开始PHD生涯,好久不做题了,手生的不行,代码能力、算法能力直线下滑。
不管以后我做什么方向,做做题目能很好地锻炼我的思维,所以以后开始继续做题,纯粹为了玩!
先整理一下线段树方面的题目吧,最近项目有用到,还有一些新的线段树的题目陆续添加吧
1、单点更新,区间查询
/* HDU1166 单点更新,对区间进行询问。 不必设置延迟标记,单点更新到叶子节点,正常进行区间查询 */ #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; #define LL(x) (x << 1) #define RR(x) ((x << 1) | 1) struct Seg_Tree_Node { int left, right; int sum; int mid() { return (left + right) / 2; } }tree[50000 * 3 + 12345]; int num[50000 + 123]; void update_info(int idx) { tree[idx].sum = tree[LL(idx)].sum + tree[RR(idx)].sum; } void build(int l, int r, int idx) { tree[idx].left = l; tree[idx].right = r; if(l == r) { tree[idx].sum = num[l]; return; } int mid = tree[idx].mid(); build(l, mid, LL(idx)); build(mid + 1, r, RR(idx)); update_info(idx); } void update(int x, int idx, int c) { if(tree[idx].left == tree[idx].right) { tree[idx].sum += c; return; } int mid = tree[idx].mid(); if(x <= mid) update(x, LL(idx), c); else update(x, RR(idx), c); update_info(idx); } int query(int l, int r, int idx) { if(l <= tree[idx].left && tree[idx].right <= r) { //printf("%d -> %d\n", tree[idx].left, tree[idx].right); return tree[idx].sum; } int mid = tree[idx].mid(); if(r <= mid) return query(l, r, LL(idx)); else if(l > mid) return query(l, r, RR(idx)); else return query(l, r, LL(idx)) + query(l, r, RR(idx)); } int main() { int T; int cas = 1; scanf("%d", &T); while(T--) { int n; scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d", &num[i]); build(1, n, 1); printf("Case %d:\n", cas++); char s[10]; int x, y; while(1) { scanf("%s", s); if(strcmp(s, "End") == 0) break; else if(strcmp(s, "Query") == 0) { scanf("%d%d", &x, &y); if(x > y) { int temp = x; x = y; y = temp; } printf("%d\n", query(x, y, 1)); } else if(strcmp(s, "Sub") == 0) { scanf("%d%d", &x, &y); update(x, 1, -y); } else if(strcmp(s, "Add") == 0) { scanf("%d%d", &x, &y); update(x, 1, y); } } } return 0; }
/* HDU1754 单点更新,区间查询 */ #include<iostream> #define LL(x) (x<<1) #define RR(x) (x<<1|1) using namespace std; struct Seg_Tree { int left,right,num; int calmid() { return (right+left)/2;} }tree[600020]; int num[200010]; int build(int left,int right,int idx) { tree[idx].left=left; tree[idx].right=right; if(left==right) { return tree[idx].num=num[left]; } int mid=tree[idx].calmid(); return tree[idx].num=max(build(left,mid,LL(idx)),build(mid+1,right,RR(idx))); } void update(int id,int x,int idx) { if(tree[idx].left==tree[idx].right) { tree[idx].num=x; return ; } int mid=tree[idx].calmid(); if(id<=mid) update(id,x,LL(idx)); else update(id,x,RR(idx)); tree[idx].num=max(tree[LL(idx)].num,tree[RR(idx)].num); } int query(int left,int right,int idx) { if(left<=tree[idx].left && right>=tree[idx].right) return tree[idx].num; int mid=tree[idx].calmid(); if(right<=mid) return query(left,right,LL(idx)); else if(left>mid) return query(left,right,RR(idx)); else return max(query(left,mid,LL(idx)),query(mid+1,right,RR(idx))); } int main() { int n,m,a,b; while(scanf("%d%d",&n,&m)!=EOF) { for(int i=1;i<=n;i++) scanf("%d",&num[i]); build(1,n,1); for(int i=1;i<=m;i++) { char str[10]; scanf("%s%d%d",&str,&a,&b); if(str[0]=='Q') printf("%d/n",query(a,b,1)); else update(a,b,1); } } return 0; }
2、区间更新,区间查询
/* HDU 1698 区间更新 */ #include<stdio.h> #define LL(x) (x<<1) #define RR(x) (x<<1|1) struct Seg_Tree { int left,right,num; int calmid() { return (left+right)/2; } } tree[300005]; void build(int left,int right,int idx) { tree[idx].left=left; tree[idx].right=right; tree[idx].num=1; if(left==right) return ; int mid=tree[idx].calmid(); if(left<=mid) build(left,mid,LL(idx)); if(right>mid) build(mid+1,right,RR(idx)); } void update(int left,int right,int x,int idx) { if(left<=tree[idx].left && right>=tree[idx].right) { tree[idx].num=x; return; } if(tree[idx].num!=-1) { tree[RR(idx)].num=tree[LL(idx)].num=tree[idx].num; tree[idx].num=-1; } int mid=tree[idx].calmid(); if(left<=mid) update(left,right,x,LL(idx)); if(right>mid) update(left,right,x,RR(idx)); } int query(int left,int right ,int idx) { if(left<=tree[idx].left && right>=tree[idx].right) { if(tree[idx].num!=-1) return tree[idx].num*(tree[idx].right-tree[idx].left+1); } int mid=tree[idx].calmid(); if(right<=mid) return query(left,mid,LL(idx)); else if(left>mid) return query(mid+1,right,RR(idx)); else return query(left,mid,LL(idx))+query(mid+1,right,RR(idx)); } int main() { int T,cas=1; scanf("%d",&T); while(T--) { int n,m; scanf("%d",&n); build(1,n,1); scanf("%d",&m); while(m--) { int a,b,c; scanf("%d%d%d",&a,&b,&c); update(a,b,c,1); } printf("Case %d: The total value of the hook is %d./n",cas++,query(1,n,1)); } return 0; }
/* POJ3468 成段更新,总区间求和 */ #include<stdio.h> #define LL(x) (x<<1) #define RR(x) (x<<1|1) struct Seg_tree { int left,right; __int64 sum,add;//用于标记下传,否则必TLE int clamid() { return (left+right)/2; } }tree[100001*3]; int num[100001]; int n,q; void build(int l,int r,int idx) { tree[idx].left=l; tree[idx].right=r; tree[idx].add=0; if(l==r) { tree[idx].sum=num[l]; return ; } int mid=tree[idx].clamid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); tree[idx].sum=tree[LL(idx)].sum+tree[RR(idx)].sum; } void Update(int l,int r,int idx,int c) { if(l<=tree[idx].left&&r>=tree[idx].right) { tree[idx].add+=c; tree[idx].sum+=c*(tree[idx].right-tree[idx].left+1); return ; } if(tree[idx].add) { tree[LL(idx)].add+=tree[idx].add; tree[LL(idx)].sum+=tree[idx].add*(tree[LL(idx)].right-tree[LL(idx)].left+1); tree[RR(idx)].add+=tree[idx].add; tree[RR(idx)].sum+=tree[idx].add*(tree[RR(idx)].right-tree[RR(idx)].left+1); tree[idx].add=0; } int mid=tree[idx].clamid(); if(r>mid) Update(l,r,RR(idx),c); if(l<=mid) Update(l,r,LL(idx),c); /*if(r>mid) Update(mid+1,r,RR(idx),c); if(l<=mid) Update(l,mid,LL(idx),c);这是错误的*/ tree[idx].sum=tree[LL(idx)].sum+tree[RR(idx)].sum; } __int64 query(int l,int r,int idx) { if(l<=tree[idx].left&&r>=tree[idx].right) return tree[idx].sum; if(tree[idx].add) { tree[LL(idx)].add+=tree[idx].add; tree[LL(idx)].sum+=tree[idx].add*(tree[LL(idx)].right-tree[LL(idx)].left+1); tree[RR(idx)].add+=tree[idx].add; tree[RR(idx)].sum+=tree[idx].add*(tree[RR(idx)].right-tree[RR(idx)].left+1); tree[idx].add=0; } int mid=tree[idx].clamid(); if(r<=mid) return query(l,r,LL(idx)); else if(l>mid) return query(l,r,RR(idx)); else return query(l,mid,LL(idx))+query(mid+1,r,RR(idx)); } int main() { while(scanf("%d%d",&n,&q)!=EOF) { for(int i=1;i<=n;i++) scanf("%d",&num[i]); build(1,n,1); for(int i=1;i<=q;i++) { char str[10]; int a,b,c; scanf("%s",str); if(str[0]=='Q') { scanf("%d%d",&a,&b); printf("%I64d/n",query(a,b,1)); } else { scanf("%d%d%d",&a,&b,&c); Update(a,b,1,c); } } } return 0; }
/* POJ2777 很裸的区间更新,区间查询 设置一个延迟标记,尽可能减少访问子节点次数 因为最多只有30种颜色,所以使用int类型进行位压缩 */ #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; #define LL(x) (x << 1) #define RR(x) ((x << 1) | 1) struct Seg_Tree_Node { int left, right; int color; bool delay; int mid() { return (left + right) / 2; } }tree[100000 * 3 + 1234]; int cnum; void update_info(int idx) { tree[idx].color = tree[LL(idx)].color | tree[RR(idx)].color; } void pushDown(int idx) { tree[LL(idx)].color = tree[idx].color; tree[LL(idx)].delay = 1; tree[RR(idx)].color = tree[idx].color; tree[RR(idx)].delay = 1; tree[idx].delay = 0; tree[idx].color = 0; } void build(int l, int r, int idx) { tree[idx].left = l; tree[idx].right = r; tree[idx].color = 1; tree[idx].delay = 0; if(l == r) return; int mid = tree[idx].mid(); build(l, mid, LL(idx)); build(mid + 1, r, RR(idx)); update_info(idx); } void update(int l, int r, int idx, int c) { if(l <= tree[idx].left && tree[idx].right <= r) { tree[idx].color = 1 << (c - 1); tree[idx].delay = 1;//打上延迟标记 return; } if(tree[idx].delay) pushDown(idx); int mid = tree[idx].mid(); if(r > mid) update(l, r, RR(idx), c); if(l <= mid) update(l, r, LL(idx), c); update_info(idx); } void query(int l, int r, int idx) { if(l <= tree[idx].left && tree[idx].right <= r) { cnum = cnum | tree[idx].color; return; } if(tree[idx].delay) pushDown(idx); int mid = tree[idx].mid(); if(r > mid) query(l, r, RR(idx)); if(l <= mid) query(l, r, LL(idx)); update_info(idx); } int cal(int num) { int sum = 0; while(num != 0) { if(num & 1) sum++; num = num >> 1; } return sum; } int main() { int l, t, o; while(scanf("%d%d%d", &l, &t, &o) != EOF) { build(1, l, 1); char s[10]; int l, r, c; for(int i = 0; i < o; i++) { scanf("%s", s); if(s[0] == 'P') { scanf("%d%d", &l, &r); if(l > r) { int temp = l; l = r; r = temp; } cnum = 0; query(l, r, 1); printf("%d\n", cal(cnum)); } else { scanf("%d%d%d", &l, &r, &c); if(l > r) { int temp = l; l = r; r = temp; } update(l, r, 1, c); } } } return 0; }
/* JOJ2445 区间更新,区间查询 这题的不同之处在于建树略微有点特别。 先用静态链表建好原始二叉树,接着DFS一遍找出每个父亲节点的管辖范围,类似于后序遍历 另外,这个题目左右子树互换不影响结果 */ #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; #define LL(x) (x << 1) #define RR(x) ((x << 1) | 1) const int MAXN = 20000 + 1234; struct EDGE { int u, v, next; }edge[MAXN * 2]; struct Seg_Tree_Node { int left, right; int sum; bool delay; int mid() { return (left + right) / 2; } }tree[MAXN * 3]; int head[MAXN]; int cnt; int vnum; bool vis[MAXN]; int lid[MAXN], rid[MAXN]; void addedge(int a, int b) { edge[cnt].u = a; edge[cnt].v = b; edge[cnt].next = head[a]; head[a] = cnt++; } int dfs(int u) { int lmin = MAXN; vis[u] = 1;//�Ѿ��߹��� for(int p = head[u]; p != -1; p = edge[p].next) { if(vis[edge[p].v]) continue; int t = dfs(edge[p].v); if(t < lmin) lmin = t; } rid[u] = ++vnum; if(lmin == MAXN) lmin = rid[u]; lid[u] = lmin; return lmin; } void build(int l, int r, int idx) { tree[idx].left = l; tree[idx].right = r; tree[idx].delay = 0; tree[idx].sum = 0; if(l == r) return; int mid = tree[idx].mid(); build(l, mid, LL(idx)); build(mid + 1, r, RR(idx)); } void pushDown(int idx) { int l = LL(idx), r = RR(idx); tree[l].sum = (tree[l].right - tree[l].left + 1) - tree[l].sum; tree[l].delay = 1 - tree[l].delay; tree[r].sum = (tree[r].right - tree[r].left + 1) - tree[r].sum; tree[r].delay = 1 - tree[r].delay; tree[idx].delay = 0; } void update_info(int idx) { int l = LL(idx), r = RR(idx); tree[idx].sum = tree[l].sum + tree[r].sum; } void update(int l, int r, int idx) { if(l <= tree[idx].left && tree[idx].right <= r) { tree[idx].sum = (tree[idx].right - tree[idx].left + 1) - tree[idx].sum; tree[idx].delay = 1 - tree[idx].delay; return; } if(tree[idx].delay) pushDown(idx); int mid = tree[idx].mid(); if(r > mid) update(l, r, RR(idx)); if(l <= mid) update(l, r, LL(idx)); update_info(idx); } int query(int l, int r, int idx) { if(l <= tree[idx].left && tree[idx].right <= r) { return tree[idx].sum; } if(tree[idx].delay) pushDown(idx); int mid = tree[idx].mid(); if(r <= mid) return query(l, r, LL(idx)); else if(l > mid) return query(l, r, RR(idx)); else return query(l, r, LL(idx)) + query(l, r, RR(idx)); update_info(idx); } int main() { int n, m; while(scanf("%d", &n) != EOF) { cnt = 0; vnum = 0; memset(head, -1, sizeof(head)); memset(vis, 0, sizeof(vis)); memset(lid, 0, sizeof(lid)); memset(rid, 0, sizeof(rid)); int a, b; for(int i = 1; i < n; i++) { scanf("%d%d", &a, &b); addedge(a, b); addedge(b, a); } dfs(1); //for(int i = 1; i <= n; i++) printf("%d: %d %d\n", i, lid[i], rid[i]); build(1, n, 1); scanf("%d", &m); char str[10]; int x; for(int i = 0; i < m; i++) { scanf("%s", str); if(str[0] == 'Q') { scanf("%d", &x); printf("%d\n", query(lid[x],rid[x], 1)); } else { scanf("%d", &x); update(lid[x], rid[x], 1); } } } return 0; }
/* 树状数组+二分同样可做 当然这题目数据量小,暴力都能过 纯粹套一下线段树的做法 属于单点更新和区间查询 线段树记录每段线段的和,访问略微有点特殊 访问可以看作是,问当和为x的时候,是第几个数 接着更新和访问一起就可以了 */ #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; #define LL(x) (x << 1) #define RR(x) ((x << 1) | 1) const int MAXN = 10000; int rid[MAXN]; int num[MAXN]; struct Seg_Tree_Node { int left, right; int sum; int mid() { return (left + right) / 2; } }tree[MAXN * 3]; void update_info(int idx) { tree[idx].sum = tree[LL(idx)].sum + tree[RR(idx)].sum; } void build(int l, int r, int idx) { tree[idx].left = l; tree[idx].right = r; if(l == r) { tree[idx].sum = 1; return; } int mid = tree[idx].mid(); build(l, mid, LL(idx)); build(mid + 1, r, RR(idx)); update_info(idx); } //查询和修改统一 int query(int c, int idx) { int ans; if(tree[idx].left == tree[idx].right) { tree[idx].sum = 0; return tree[idx].left; } int mid = tree[idx].mid(); if(tree[LL(idx)].sum >= c) ans = query(c, LL(idx)); else ans = query(c - tree[LL(idx)].sum, RR(idx)); update_info(idx); return ans; } int main() { int n; while(scanf("%d", &n) != EOF) { for(int i = 2; i <= n; i++) scanf("%d", &rid[i]); build(1, n, 1); for(int i = n; i >= 2; i--) { num[i] = query(rid[i] + 1, 1); } num[1] =query(1, 1); for(int i = 1; i <= n; i++) printf("%d\n", num[i]); } return 0; }
/*POJ 2528这题目需要离散化,离散化的时候注意一下,相连的数离散化后相差为1, 否则相差为2更新时候使用延迟标记最后询问的时候一次到底*/ #include<stdio.h> #include<algorithm> #include<string.h> #define LL(x) (x<<1) #define RR(x) (x<<1|1) using namespace std; struct T { int num,id,flag,t; } s[20010]; struct Seg_Tree { int left,right,col; int mid() { return (left+right)/2;} }tree[30010*2*3]; int x[10010],y[10010],ans; bool flag[20010*3]; bool cmp(T a, T b) { return a.num<b.num; } void build(int l,int r,int idx) { tree[idx].left=l; tree[idx].right=r; tree[idx].col=-1; if(l==r) return ; int mid=tree[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } void update(int l,int r,int c,int idx) { if(l<=tree[idx].left&&r>=tree[idx].right) { tree[idx].col=c; return; } if(tree[idx].col!=-1) { tree[LL(idx)].col=tree[RR(idx)].col=tree[idx].col; tree[idx].col=-1; } int mid=tree[idx].mid(); if(l<=mid) update(l,r,c,LL(idx)); if(r>mid) update(l,r,c,RR(idx)); } void query(int l,int r,int idx) { if(tree[idx].col!=-1) { if(!flag[tree[idx].col]) { ans++; flag[tree[idx].col]=true; } return;//important } int mid=tree[idx].mid(); if(l<=mid) query(l,r,LL(idx)); if(r>mid) query(l,r,RR(idx)); } int main() { int T,n; scanf("%d",&T); while(T--) { memset(flag,false,sizeof(flag)); scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%d%d",&x[i],&y[i]); s[2*i].id=i; s[2*i].num=x[i]; s[2*i].flag=0; s[2*i+1].id=i; s[2*i+1].num=y[i]; s[2*i+1].flag=1; } sort(s,s+2*n,cmp); s[0].t=0; for(int i=1; i<2*n; i++) if(s[i].num!=s[i-1].num) { if(s[i].num-1>s[i-1].num) s[i].t=s[i-1].t+2; else s[i].t=s[i-1].t+1; } else s[i].t=s[i-1].t; for(int i=0; i<2*n; i++) if(s[i].flag==0) x[s[i].id]=s[i].t; else y[s[i].id]=s[i].t; build(0,s[2*n-1].t,1); for(int i=0; i<n; i++) update(x[i],y[i],i,1); ans=0; query(0,s[2*n-1].t,1); printf("%d\n",ans); } return 0; }
/* POJ 3667 Hotel 当年的第一道用线段树做区间合并的题目 delay做延迟标记 lval表示左边的最长连续区间 rval表示右边的最长连续区间 lval表示这个线段的最长连续区间 接着维护上面几个变量即可 因为每次查询后都要更新,所以这个query函数里可以暂时不加更新 */ #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define LL(x) (x << 1) #define RR(x) ((x << 1) | 1) const int MAXN = 50000 + 1234; struct Seg_Tree_Node { int left, right; int delay; int cval, lval, rval; int mid() { return (left + right) / 2; } }tree[MAXN * 3]; void build(int l, int r, int idx) { tree[idx].left = l; tree[idx].right = r; tree[idx].cval = tree[idx].lval = tree[idx].rval = r - l + 1; tree[idx].delay = -1;//0 or 1 or -1 if(l == r) return; int mid = tree[idx].mid(); build(l, mid, LL(idx)); build(mid + 1, r, RR(idx)); } void pushdown(int idx) { int l = LL(idx), r = RR(idx); tree[l].cval = tree[l].lval = tree[l].rval = tree[idx].delay * (tree[l].right - tree[l].left + 1); tree[l].delay = tree[idx].delay; tree[r].cval = tree[r].lval = tree[r].rval = tree[idx].delay * (tree[r].right - tree[r].left + 1); tree[r].delay = tree[idx].delay; tree[idx].delay = -1; } void update_info(int idx) { int l = LL(idx), r = RR(idx); tree[idx].lval = tree[l].lval; if(tree[l].lval == tree[l].right - tree[l].left + 1) tree[idx].lval += tree[r].lval; tree[idx].rval = tree[r].rval; if(tree[r].rval == tree[r].right - tree[r].left + 1) tree[idx].rval += tree[l].rval; tree[idx].cval = max(tree[l].cval, tree[r].cval); tree[idx].cval = max(tree[idx].cval, tree[l].rval + tree[r].lval); } void update(int l, int r, int c, int idx) { if(l <= tree[idx].left && tree[idx].right <= r) { tree[idx].cval = tree[idx].lval = tree[idx].rval = c * (tree[idx].right - tree[idx].left + 1); tree[idx].delay = c; return; } if(tree[idx].delay != -1) pushdown(idx); int mid = tree[idx].mid(); if(r > mid) update(l, r, c, RR(idx)); if(l <= mid) update(l, r, c, LL(idx)); update_info(idx); } int query(int c, int idx) { if(tree[idx].left == tree[idx].right) { if(c == 1) return tree[idx].left; return 0; } if(tree[idx].delay != -1) pushdown(idx); int mid = tree[idx].mid(); int l = LL(idx), r = RR(idx); if(tree[l].cval >= c) return query(c, LL(idx)); else if(tree[l].rval + tree[r].lval >= c) return tree[l].right - tree[l].rval + 1; else if(tree[r].cval >= c) return query(c, RR(idx)); else return 0; } int main() { int n, m; while(scanf("%d%d", &n, &m) != EOF) { build(1, n, 1); int a, b, c; for(int i = 0; i < m; i++) { scanf("%d", &a); if(a == 1) { scanf("%d", &b); int ans = query(b, 1); printf("%d\n", ans); if(ans != 0) update(ans, ans + b - 1, 0, 1); } else { scanf("%d%d", &b, &c); update(b, b + c - 1, 1, 1); } //printf("%d\n", tree[1].cval); } } return 0; }
/*HDU 1540 与前面那题Hotel相似。 单点更新,查询方式稍微有些区别,变化不大。 */ #include<stdio.h> #include<string.h> #define LL(x) (x<<1) #define RR(x) (x<<1|1) int stack[50010],n,m; struct Seg_Tree { int l,r; int cval,lval,rval; void doit(int st) { cval=lval=rval=( st==1? 0 : dis() ) ;} int dis() { return (r-l+1) ;} int mid() { return (l+r)/2 ;} }tree[50010*3]; int max(int a,int b) { if(a>b) return a; return b; } void build(int left,int right,int idx) { tree[idx].l=left; tree[idx].r=right; tree[idx].doit(0); if(left==right) return; int mid=tree[idx].mid(); build(left,mid,LL(idx)); build(mid+1,right,RR(idx)); } void update(int x,int st,int idx) { if(tree[idx].l==tree[idx].r) { tree[idx].doit(st); return ; } int mid=tree[idx].mid(); if(x<=mid) update(x,st,LL(idx)); else update(x,st,RR(idx)); tree[idx].cval=max(tree[LL(idx)].rval+tree[RR(idx)].lval, max(tree[LL(idx)].cval,tree[RR(idx)].cval)); tree[idx].lval=tree[LL(idx)].lval; tree[idx].rval=tree[RR(idx)].rval; if(tree[LL(idx)].cval==tree[LL(idx)].dis()) tree[idx].lval+=tree[RR(idx)].lval; if(tree[RR(idx)].cval==tree[RR(idx)].dis()) tree[idx].rval+=tree[LL(idx)].rval; } int query(int x,int idx) { if(tree[idx].l==tree[idx].r || tree[idx].cval==0 || tree[idx].cval==tree[idx].dis() ) { return tree[idx].cval; } int mid=tree[idx].mid(); if(x<=mid) { if(x>tree[LL(idx)].r-tree[LL(idx)].rval) //return query(x,LL(idx))+query(tree[RR(idx)].l,RR(idx)); return query(x,LL(idx))+tree[RR(idx)].lval; else return query(x,LL(idx)); } else { if(x<tree[RR(idx)].l+tree[RR(idx)].lval) //return query(tree[LL(idx)].r,LL(idx))+query(x,RR(idx)); return query(x,RR(idx))+tree[LL(idx)].rval; else return query(x,RR(idx)); } } int main() { while(scanf("%d%d",&n,&m)!=EOF) { memset(tree,0,sizeof(tree)); memset(stack,0,sizeof(stack)); int num=0; build(1,n,1); for(int i=1;i<=m;i++) { char ch[2]; scanf("%s",&ch); if(ch[0]=='D') { int x; scanf("%d",&x); update(x,1,1); stack[num++]=x; } else if(ch[0]=='Q') { int x; scanf("%d",&x); printf("%d\n",query(x,1)); } else { if(num==0) continue; update(stack[--num],0,1); } } } return 0; }
/* 其实就是HOTEL的加强版,甚至于HOTEL的3个函数都没有任何变化。 内存共四个指令,第一次是New x就是找一段长为X的最左边的区间,这个和HOTEL是没有区别,还是用那三个函数找到最左边的区间并加以更新,ST=1 第二个指令是Free x就是找一个包含X的区间,咋一看以为要重写一个QUERY函数,其实没有必要,使用VECTOR数组保存下每次占领的区间,并且由于VECTOR是向量,可以删除中间的,并任意在中间加区间,十分方便。那我们现在向量里找到那个区间,接着进行更新,ST=0 第三个指令是Get x就是找到第X个区间的范围,用VECTOR的记录很快就能找到 第四个指令Reset,很方面,更新一下即可 */ #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #define LL(x) (x << 1) #define RR(x) ((x << 1) | 1) const int MAXN = 50000 + 1234; using namespace std; struct EDGE { int begin, end; }; vector<EDGE> que; struct Seg_Tree { int left, right; int lval, rval, cval; int delay; int mid() { return (left + right) / 2; } } tree[MAXN * 3]; void build(int l, int r, int idx) { tree[idx].left = l; tree[idx].right = r; tree[idx].lval = tree[idx].rval = tree[idx].cval = tree[idx].right - tree[idx].left + 1; tree[idx].delay = -1; if(l == r) return; int mid = tree[idx].mid(); build(l, mid, LL(idx)); build(mid + 1, r, RR(idx)); } void pushdown(int idx) { int l = LL(idx), r= RR(idx); tree[l].delay = tree[r].delay = tree[idx].delay; tree[l].cval = tree[l].lval = tree[l].rval = tree[idx].delay * (tree[l].right - tree[l].left + 1); tree[r].cval = tree[r].lval = tree[r].rval = tree[idx].delay * (tree[r].right - tree[r].left + 1); tree[idx].delay = -1; } void updateinfo(int idx) { int l = LL(idx), r= RR(idx); tree[idx].cval = max(tree[l].cval, tree[r].cval); tree[idx].cval = max(tree[idx].cval, tree[l].rval + tree[r].lval); tree[idx].lval = tree[l].lval; if(tree[l].lval == tree[l].right - tree[l].left + 1) tree[idx].lval += tree[r].lval; tree[idx].rval = tree[r].rval; if(tree[r].rval == tree[r].right - tree[r].left + 1) tree[idx].rval += tree[l].rval; } void update(int l, int r, int c, int idx) { if(l <= tree[idx].left && tree[idx].right <= r) { tree[idx].delay = c; tree[idx].cval = tree[idx].lval = tree[idx].rval = c * (tree[idx].right - tree[idx].left + 1); return; } if(tree[idx].delay != -1) pushdown(idx); int mid = tree[idx].mid(); if(l <= mid) update(l, r, c, LL(idx)); if(r > mid) update(l, r, c, RR(idx)); updateinfo(idx); } int query(int x, int idx) { if(tree[idx].left == tree[idx].right) { return tree[idx].left; } if(tree[idx].delay != -1) pushdown(idx); int mid = tree[idx].mid(); int l = LL(idx), r = RR(idx); if(tree[l].cval >= x) return query(x, l); else if(tree[l].rval + tree[r].lval >= x) return mid - tree[l].rval + 1; else if(tree[r].cval >= x) return query(x, r); else return -1;//no possible } int half_search(int x) { int left = 0, right = que.size() - 1; while(left <= right) { int mid = (left + right) / 2; if(que[mid].begin <= x) left = mid + 1; else right = mid - 1; } return left; //left是第一个begin大于x的区间(不等于),注意特殊情况就是队列为空,只有1个的时候也成立 } int main() { int n, m; while(scanf("%d%d", &n, &m) != EOF) { que.clear(); build(1, n, 1); char s[10]; int x; for(int i = 0; i < m; i++) { scanf("%s", s); if(strcmp(s, "New") == 0) { scanf("%d", &x); if(tree[1].cval < x) puts("Reject New"); else { EDGE tmp; tmp.begin = query(x, 1); tmp.end = tmp.begin + x - 1; int pos = half_search(tmp.begin); que.insert(que.begin() + pos, tmp); update(tmp.begin, tmp.end, 0, 1); printf("New at %d\n", tmp.begin); } } else if(strcmp(s, "Free") == 0) { scanf("%d", &x); int pos = half_search(x) - 1; if(pos < 0 || que[pos].end < x) puts("Reject Free"); else { update(que[pos].begin, que[pos].end, 1, 1); printf("Free from %d to %d\n", que[pos].begin, que[pos].end); que.erase(que.begin() + pos, que.begin() + pos + 1); } } else if(strcmp(s, "Get") == 0) { scanf("%d", &x); if(x > que.size()) puts("Reject Get"); else { printf("Get at %d\n", que[--x].begin); } } else { puts("Reset Now"); que.clear(); update(1, n, 1, 1); } } puts(""); } return 0; }