这道题作为前天的模拟赛题,考场上我在还剩一个半小时的情况下居然选择求稳打暴力,水过了40分,然后就坐看cansult和refun这俩dalaoAK...
一开始我的想法是,把区间看成两点之间不包含端点的小区间和端点构成的集合,然后分开处理,这个做法可能暴力还是可以的,然而如果要用线段树的话,就要开两颗线段树
正确做法应该是把每个点拆成三个点,)就是标记第一个点,】和【就是标记第二个点,(就是标记第三个点
然后我还把数据范围>=0看成>=1,最后的输出也很容易出错
#include<iostream>
#include<cstdio>
#include<cstring>
#define ls ((root<<1)+1)
#define rs ((root<<1)+2)
#define mid ((l+r)>>1)
using namespace std;
int N,n,a[400000];
struct order{
int type,l,r;
}q[200001];
struct Node{
int mul,add;
}tree[2000000];
void init(){
char ch; int l,r;
while (cin>>ch){
n++;
if (ch=='U') q[n].type=1;
if (ch=='I') q[n].type=2;
if (ch=='D') q[n].type=3;
if (ch=='C') q[n].type=4;
if (ch=='S') q[n].type=5;
cin>>ch>>l;
l=l*3+2+(ch=='(');
cin>>ch>>r>>ch;
r=r*3+2-(ch==')');
q[n].l=l; q[n].r=r;
N=max(N,q[n].r);
}
}
void pushdown(int root){
tree[ls].add=tree[root].mul*tree[ls].add+tree[root].add;
tree[rs].add=tree[root].mul*tree[rs].add+tree[root].add;
tree[ls].mul*=tree[root].mul;
tree[rs].mul*=tree[root].mul;
tree[root].add=0;
tree[root].mul=1;
}
void Mul(int root,int l,int r,int l1,int r1,int val){
if (l>=l1&&r<=r1){;
tree[root].mul*=val;
tree[root].add*=val;
return;
}
pushdown(root);
if (l1<=mid) Mul(ls,l,mid,l1,r1,val);
if (r1>mid) Mul(rs,mid+1,r,l1,r1,val);
}
void Add(int root,int l,int r,int l1,int r1,int val){
if (l>=l1&&r<=r1){;
tree[root].add+=val;
return;
}
pushdown(root);
if (l1<=mid) Add(ls,l,mid,l1,r1,val);
if (r1>mid) Add(rs,mid+1,r,l1,r1,val);
}
int query(int root,int l,int r,int pos){
if (l==r) return tree[root].add;
pushdown(root);
if (pos<=mid) return query(ls,l,mid,pos);
else return query(rs,mid+1,r,pos);
}
void build(int root,int l,int r){
tree[root].mul=1;
if (l==r){
tree[root].add=-1;
return;
}
build(ls,l,mid);
build(rs,mid+1,r);
}
int main(){
init();
int i,l,r,j;
build(0,0,N);
for (i=1;i<=n;i++){
if (q[i].type==1){
Mul(0,0,N,q[i].l,q[i].r,0);
Add(0,0,N,q[i].l,q[i].r,1);
continue;
}
if (q[i].type==2){
if (q[i].l>=1) {
Mul(0,0,N,1,q[i].l-1,0);
Add(0,0,N,1,q[i].l-1,-1);
}
if (q[i].r<N){
Mul(0,0,N,q[i].r+1,N,0);
Add(0,0,N,q[i].r+1,N,-1);
}
continue;
}
if (q[i].type==3){
Mul(0,0,N,q[i].l,q[i].r,0);
Add(0,0,N,q[i].l,q[i].r,-1);
continue;
}
if (q[i].type==4){
if (q[i].l>=1) {
Mul(0,0,N,1,q[i].l-1,0);
Add(0,0,N,1,q[i].l-1,-1);
}
if (q[i].r<N){
Mul(0,0,N,q[i].r+1,N,0);
Add(0,0,N,q[i].r+1,N,-1);
}
Mul(0,0,N,q[i].l,q[i].r,-1);
continue;
}
Mul(0,0,N,q[i].l,q[i].r,-1);
}
bool flag=1;
for (i=1;i<=N;i++){
a[i]=query(0,0,N,i);
if (a[i]==1) flag=0;
}
if (flag){
cout<<"empty set";
return 0;
}
a[N+1]=-1;
for (i=1;i<=N;i++){
if (a[i]==-1) continue;
l=i;
for (i=l+1;i<=N+1;i++)//这个地方要开到N+1,因为如果开到N,a[N]!=-1时会出错
if (a[i]==-1) break;
r=--i;
char c1=(l%3==2)?'[':'(',c2=(r%3==2)?']':')';
printf("%c%d,%d%c ",c1,(l-1)/3,(r-1)/3,c2);
}
return 0;
}