poj 3225
来源:互联网 发布:java写web服务器 编辑:程序博客网 时间:2024/06/13 21:42
这道题目纠结死了,想了各种实现终于A了。还有没看清题意,空集的时候没输出“empty set”,wa到吐。
线段树成段更新。
U:把区间[l,r]覆盖成1
I:把[-∞,l)(r,∞]覆盖成0
D:把区间[l,r]覆盖成0
C:把[-∞,l)(r,∞]覆盖成0 , 且[l,r]区间0/1互换
开闭区间的问题可以把(i,i+1)抽象为一个点,最后得到2*65535+1个点,比如(0,1)这个区间就抽象成了点1。
首先要确定线段树中节点所维护的信息的含义。这里每个节点维护两个信息。1.这一整段被涂成某一值。2.flag来表示取反,flag=1表示本区间和其子区间在没有进行此次取反所确定的值的基础上取反,flag的作用是相互抵消重叠的。某一区间的值(线段树上节点所代表的区间)最终的结果是确定这一区间的值的祖先区间的值和从根节点到确定这一区间的值的祖先区间的路径上各个flag共同作用的结果。push_down,update,query实现细节见代码。
#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#include <cmath>#include <stack>#include <vector>#include <map>#include <string>#define eps 1e-8#define LL long long#define myabs(x) ((x)>0?(x):(-(x)))using namespace std;const int inf=0x3f3f3f3f;const int maxn=65536*2+10;int in_set[maxn*4],flag[maxn*4],ch;int ql,qr,update_val,qans;void push_down2(int no){ int ln=no*2+1,rn=no*2+2; if(flag[no]) { flag[ln]=flag[ln]^1; flag[rn]=flag[rn]^1; flag[no]=0; }}void push_down1(int no){ int ln=no*2+1,rn=no*2+2; if(in_set[no]!=-1) { in_set[ln]=in_set[rn]=in_set[no]; push_down2(ln); push_down2(rn); in_set[no]=-1; }}void update(int no,int left,int right){ if(ql>qr) return; // if(left>=ql&&right<=qr) { flag[no]=0; in_set[no]=update_val; return ; } int mid=left+((right-left)>>1); push_down1(no); push_down2(no); if(ql<=mid) update(no*2+1,left,mid); if(qr>mid) update(no*2+2,mid+1,right);}void change(int no,int left,int right){ if(ql>qr) return; if(left>=ql&&right<=qr) { flag[no]^=1; return; } push_down1(no); push_down2(no); int mid=left+((right-left)>>1); if(ql<=mid) change(no*2+1,left,mid); if(qr>mid) change(no*2+2,mid+1,right);}void query(int no,int left,int right){ if(flag[no]==1) ch^=1; if(in_set[no]!=-1) { qans=in_set[no]; return; } if(left==right) return; int mid=left+((right-left)>>1); if(ql<=mid) query(no*2+1,left,mid); else query(no*2+2,mid+1,right);}int main(){ char op,k1,k2; int num1,num2; memset(in_set,-1,sizeof(in_set)); in_set[0]=0; int n=65535*2; while(~scanf("%c",&op)) { getchar(); scanf("%c%d,%d%c",&k1,&num1,&num2,&k2); getchar(); if(k1=='(') num1=num1*2+1; else num1=num1*2; if(k2==')') num2=num2*2-1; else num2=num2*2; if(op=='U') { ql=num1; qr=num2; update_val=1; update(0,0,n); } else if(op=='I') { ql=0; qr=num1-1; update_val=0; update(0,0,n); ql=num2+1; qr=n; update(0,0,n); } else if(op=='D') { ql=num1; qr=num2; update_val=0; update(0,0,n); } else if(op=='C') { ql=0; qr=num1-1; update_val=0; update(0,0,n); ql=num2+1; qr=n; update(0,0,n); ql=num1; qr=num2; change(0,0,n); } else { ql=num1; qr=num2; change(0,0,n); } } int flag=0,i; int cur=-1,left,right; for(i=0;i<=n;i++) { ql=i; ch=0; qans=-1; query(0,0,n); qans^=ch; if(qans==1) { if(cur==-1) { left=ql; cur=left; } else continue; } else { if(cur!=-1) { if(flag) printf(" "); else flag=1; right=ql-1; if(left%2) printf("%c%d,",'(',(left-1)/2); else printf("%c%d,",'[',left/2); if(right%2) printf("%d%c",(right+1)/2,')'); else printf("%d%c",right/2,']'); cur=-1; } else continue; } } if(qans==1&&cur!=-1) { if(flag) printf(" "); else flag=1; right=n; if(left%2) printf("%c%d,",'(',(left-1)/2); else printf("%c%d,",'[',left/2); if(right%2) printf("%d%c",(right+1)/2,')'); else printf("%d%c",right/2,']'); } if(!flag) printf("empty set\n"); return 0;}
- poj 3225
- POJ 3225
- POJ 3225
- poj 3225
- poj-3225
- poj 3225
- poj 3225(线段树)
- poj 3225(线段树)
- POJ 3225 次短路
- POJ 3225 Roadblocks
- poj 3225 区间
- POJ 3225 区间 中文
- POJ
- poj
- POJ
- POJ
- poj
- poj
- Android Sqlite常见异常的原因举例
- 数据持久化
- linux磁盘分区fdisk命令详解
- 纪录下Mac下面编译curl的过程
- 数据库索引技术
- poj 3225
- android 编译 清除配置及以前的编译信息
- string类型转为对应的枚举类型,使用Enum.Parse
- zoj 1657
- 程序猿也爱学英语
- "Berkeley DB"数据库的优点和不足之处
- 黑马程序员 java入门:其他语句流程控制语句
- shell经典,shell十三问
- 自顶向下的表归并排序的实现,使用表长来分拆表