[BZOJ3189][Coci2011][扫描线][线段树]Slika

来源:互联网 发布:淘宝新店卖啥好 编辑:程序博客网 时间:2024/06/16 12:49

首先发现LOAD和与其对应的SAVE之间的操作是没用的,所以可以O(m)扫两遍出去SAVE和LOAD操作。

对于这种矩形覆盖的问题,可以用扫面线加线段树处理。
开两棵线段树,用来记录(x+y)为奇数或偶数的时候被覆盖的情况,我们不妨扫描线扫x坐标,那么随着x+1,只要交换一下两颗线段树就可以了。

对于线段树中的一个结点,开一个set记录一下覆盖了这个结点表示的区间的颜色以及时间,以时间为关键字(我直接记录时间,在外面开个数组记录每个时间对应的颜色),这样就相当于区间覆盖,单点查询。

本地跑得贼慢,交到OJ上跑得比被抓的余畅还

#include <cstdio>#include <iostream>#include <algorithm>#include <set>#include <vector>#define N 1010#define M 100010using namespace std;int n,m,k,t;int S[M],cl[M];char c[N];struct stp{  int op,x1,y1,x2,y2,c,t;}A[M];vector<stp> b[N],e[N];struct seg{  int l,r;  set<int,greater<int> > S;};struct tree{  int L,R,Maxx;  seg T[2][N<<3];  tree(){ L=0; R=1; }  void Swap(){ swap(L,R); }  void insert(int g,int l,int r,int t,int p){    if(T[p][g].l==l&&T[p][g].r==r) return (void)T[p][g].S.insert(t);    int mid=T[p][g].l+T[p][g].r>>1;    if(r<=mid) insert(g<<1,l,r,t,p);    else if(l>mid) insert(g<<1|1,l,r,t,p);    else insert(g<<1,l,mid,t,p),insert(g<<1|1,mid+1,r,t,p);  }  void erase(int g,int l,int r,int x,int p){    if(T[p][g].l==l&&T[p][g].r==r) return (void)T[p][g].S.erase(x);     int mid=T[p][g].l+T[p][g].r>>1;    if(r<=mid) erase(g<<1,l,r,x,p);    else if(l>mid) erase(g<<1|1,l,r,x,p);    else erase(g<<1,l,mid,x,p),erase(g<<1|1,mid+1,r,x,p);  }  void erase(stp x){    if(((x.x2-x.x1+1)&1)^(x.y1&1))      erase(1,x.y1,x.y2,x.t,L);    else      erase(1,x.y1,x.y2,x.t,R);  }  void insert(stp x){    if(x.y1&1) insert(1,x.y1,x.y2,x.t,L);    else insert(1,x.y1,x.y2,x.t,R);  }  void query(int g,int x,int p){    if(!T[p][g].S.empty()) Maxx=max(Maxx,*T[p][g].S.begin());    if(T[p][g].l==T[p][g].r) return ;    int mid=T[p][g].l+T[p][g].r>>1;    if(x<=mid) query(g<<1,x,p);    else query(g<<1|1,x,p);  }  int query(int x){    Maxx=0; query(1,x,(x&1)?L:R);    return Maxx;  }  void Build(int g,int l,int r,int p){    T[p][g].l=l; T[p][g].r=r; T[p][g].S.clear();    if(l==r) return ;    int mid=l+r>>1;    Build(g<<1,l,mid,p); Build(g<<1|1,mid+1,r,p);  }  void build(){    Build(1,1,n,0); Build(1,1,n,1);  }}T;inline char nc(){  static char buf[100000],*p1=buf,*p2=buf;  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void rea(int &x){  char c=nc(); x=0;  for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());}inline void rea(char *x){  char c=nc(); int len=0;  for(;c>'Z'||c<'A';c=nc());for(;c>='A'&&c<='Z';x[len++]=c,c=nc());}int main(){  rea(n); rea(k); rea(m); cl[0]=1;  for(int i=1;i<=m;i++){    rea(c); A[i].t=i;    if(c[0]=='S') A[i].op=1;    else if(c[0]=='L') A[i].op=2,rea(A[i].c);    else{      rea(A[i].c),rea(A[i].x1),rea(A[i].y1),rea(A[i].x2),rea(A[i].y2);      A[i].x1++; A[i].x2++; A[i].y1++; A[i].y2++;      cl[i]=A[i].c;     }  }  for(int i=1;i<=m;i++) if(A[i].op==1) S[++t]=i;  /*for(int i=m;i>0;i--){    if(A[i].op==0) printf("%d %d\n",A[i].x1,A[i].x2);    else if(A[i].op==2) i=S[A[i].c];  }  return 0;*/  for(int i=m;i>0;i--){    if(A[i].op==0){      b[A[i].x1].push_back(A[i]);      e[A[i].x2+1].push_back(A[i]);    }    else if(A[i].op==2) i=S[A[i].c];  }  T.build();  for(int i=1;i<=n;i++,putchar('\n')){    T.Swap();    for(int j=0;j<e[i].size();j++)      T.erase(e[i][j]);    for(int j=0;j<b[i].size();j++)      T.insert(b[i][j]);    for(int j=1;j<=n;j++)      printf("%d ",cl[T.query(j)]);  }  return 0;}
0 0
原创粉丝点击