POJ-3225 Help with Intervals-线段树/成段更新+倍增区间法
来源:互联网 发布:最长公共子序列c语言 编辑:程序博客网 时间:2024/04/28 22:41
题意:给一个0-65535的区间,区间端点为L,R 区间有开区间闭区间之分,一开始你拥有一个S区间,为全空的区间
n次操作,每次操作有4种,
U: 把T区间L,R覆盖成1 (S U T)
I:把求给出T区间,求S和T交集,也就是把[-∞,l)(r,∞]覆盖成0
D:用原区间S减去所给区间T,也就是把 区间T置为零
C:用所给区间T减去S,然后把结果赋值给S,也就是把把[-∞,l)(r,∞]覆盖成0,把【l,r】取反
S:求异或,直接把区间【l,r】取反
上面的操作都可以用线段树的区间更新完成,分别是一个set操作,和一个求异或的操作,我们下放延迟标记的时候,注意分清先后,先下放set操作,并且set操作之后需要清空异或标记。
对于异或操作,如果当前节点有set标记,那么只需要把set标记取反即可,如果没有set标记则取反异或标记
还有一个很关键的问题是开闭区间的问题,我们用倍增区间法来解决此问题
(l, r) --> [2 * l + 1, 2 * r - 1](l, r] --> [2 * l + 1, 2 * r][l, r) --> [2 * l, 2 * r - 1][l, r] --> [2 * l, 2 *r]
我们用偶数点代表整数点,奇数点代表两个整数点之间的 所有非整数点,那么问题便解决了.
直接把端点乘2,左开则l++,右开则r--, 处理完后 最后输出 的端点为 l/2 (r+1)/2 如果l或r为奇数,对应开区间,反之闭区间
<span style="font-size:14px;">#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <algorithm>#include <queue>#include <map>#include <set>#include <vector>#include <iostream>using namespace std;#define ptf(ar1,ar2) printf("%d:%d\n",ar1,ar2);typedef __int64 ll;const ll maxn = 131570+500;int vis[131570+500]; struct tree{int set[maxn*4],yihuo[maxn*4];void pd_set(int i,int l,int r){ if (set[i]!=-1){set[i<<1]=set[i<<1|1]=set[i]; yihuo[i<<1]=yihuo[i<<1|1]=yihuo[i]=0; set[i]=-1;} if (yihuo[i]){if (set[i<<1]!=-1) set[i<<1]^=1;else yihuo[i<<1]^=1;if (set[i<<1|1]!=-1) set[i<<1|1]^=1;elseyihuo[i<<1|1]^=1;yihuo[i]=0; }}void update(int l,int r,int ql,int qr,int i,int val,int op){if (ql>r||qr<l) return ;if (ql<=l&&qr>=r){ if (op){if (set[i]!=-1) set[i]^=1;else yihuo[i]^=1; }else{set[i]=val; yihuo[i]=0;}return ;}pd_set(i,l,r); int m=(l+r)>>1;update(l,m,ql,qr,i<<1,val,op);update(m+1,r,ql,qr,i<<1|1,val,op); } void init(){//memset(sum,0,sizeof(sum));//memset(yihuo,0,sizeof(yihuo));//memset(set,-1,sizeof(set));}int query2( int l,int r,int i){ if (l==r){if (set[i]==1) vis[r]=1;return 0;}pd_set(i,l,r);int mid=(l+r)>>1;query2(l,mid,i<<1); query2(mid+1,r,i<<1|1);}};tree tp ;int main( ){ char op; int l,r; char lrat,rrat; tp.init();while(scanf("%c %c%d,%d%c",&op,&lrat,&l,&r,&rrat)!=EOF) {getchar(); l*=2; r*=2; if (lrat=='(') l++; if (rrat==')') r--; if (op=='U') tp.update(0,131570,l,r,1,1,0); if (op=='I') { tp.update(0,131570,0,l-1,1,0,0); tp.update(0,131570,r+1,131570,1,0,0); } if (op=='D') tp.update(0,131570,l,r,1,0,0); if (op=='C') { tp.update(0,131570,0,l-1,1,0,0); tp.update(0,131570,r+1,131570,1,0,0); tp.update(0,131570,l,r,1,1,1); } if (op=='S') tp.update(0,131570,l,r,1,1,1); }int i;tp.query2(0,131570 ,1); int line=0; int exist=0; for( i=0; i<=131570 ; i++) { if (vis[i]) { exist=1; if (line) printf(" "); int j=i+1; while(vis[j]&&j<=131570) j++; j--; if (i%2) printf("("); else printf("["); printf("%d,%d",i/2,(j+1)/2); if (j%2) printf(")"); else printf("]"); line=1; i=j; } }if (exist==0)printf("empty set");printf("\n");return 0;}</span>
0 0
- POJ-3225 Help with Intervals-线段树/成段更新+倍增区间法
- POJ 3225 Help with Intervals 线段树 成段更新
- POJ 3225 Help with Intervals 线段树 成段更新
- POJ 3225 Help with Intervals(区间更新 + 倍增区间)
- POJ 3225 Help with Intervals (线段树,区间更新)
- poj 3225 Help with Intervals(线段树区间更新)
- poj 3225 Help with Intervals(线段树+区间更新)
- POJ 3225 Help with Intervals (线段树 成段更新, 懒惰标记*2)
- POJ 3255 Help with Intervals (线段树区间更新)
- poj 3225 线段树区间更新,区间询问 Help with Intervals
- POJ 3225——Help with Intervals(线段树,成段替换+区间异或+hash)
- POJ 3225 Help with Intervals --线段树区间操作
- POJ 3225 Help with Intervals【线段树 区间更新 异或运算】
- POJ3225 Help with Intervals 线段树区间更新
- POJ 3225 Help with Intervals 线段树
- POJ 3225 Help with Intervals 线段树
- POJ 3225 Help with Intervals 线段树
- poj 3225 Help with Intervals[线段树]
- quick-cocos2dx scheduler.scheduleGlobal坑
- POJ 3074 Sudoku(数独|Dancing Links精确覆盖)
- 深入安卓Package Manager和Package Installer
- Android PackageManagerService分析二:安装APK
- how to calculate the QR decomposition of a matrix
- POJ-3225 Help with Intervals-线段树/成段更新+倍增区间法
- 102. Binary Tree Level Order Traversal
- Codeforces 624A Save Luke
- 五分钟搞懂后缀数组!后缀数组解析以及应用(附详解代码)
- AIM Tech Round (Div. 2) C. Graph and String(二分图染色 | 贪心)
- 编程新手我觉得需要掌握的五个重要东西
- hdoj 1385 Minimum Transport Cost(floyd 记录最短路径)
- Ubuntu 学习笔记之——下载神器aria2
- Codeblocks GDB调试器设置与使用