zoukankan      html  css  js  c++  java
  • bzoj 3226 [Sdoi2008]校门外的区间(线段树)

    3226: [Sdoi2008]校门外的区间

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 615  Solved: 227
    [Submit][Status][Discuss]

    Description

     
      受校门外的树这道经典问题的启发,A君根据基本的离散数学的知识,抽象出5种运算维护集合S(S初始为空)并最终输出S。现在,请你完成这道校门外的树之难度增强版——校门外的区间。
     
      5种运算如下:
    U T
    S∪T
    I T
    S∩T
    D T
    S-T
    C T
    T-S
    S T
    S⊕T
      基本集合运算如下:
    A∪B
    {x : xÎA or xÎB}
    A∩B
    {x : xÎA and xÎB}
    A-B
    {x : xÎA and xÏB}
    A⊕B
    (A-B)∪(B-A)
     

    Input

      输入共M行。
      每行的格式为X T,用一个空格隔开,X表示运算的种类,T为一个区间(区间用(a,b), (a,b], [a,b), [a,b]表示)。
     

    Output

     
      共一行,即集合S,每个区间后面带一个空格。若S为空则输出"empty set"。
     

    Sample Input

    U [1,5]
    D [3,3]
    S [2,4]
    C (1,5)
    I (2,3]

    Sample Output

    (2,3)

    HINT

    对于 100% 的数据,0≤a≤b≤65535,1≤M≤70000

    Source

    【思路】

           线段树。

           因为开区间所以扩大一倍就好了。

       转化集合操作为线段树上的操作

           U 将a,b设为1

           I 将1..a-1,b+1..n设为0

           D 将a..b设为0

           C 将1..a-1,b+1..n设为0 取反a..b

           S 取反a..b

           写一个支持set与取反的线段树。

    【代码】

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<algorithm>
      4 using namespace std;
      5 
      6 const int N = 150000+10;
      7 
      8 struct Tree{ int l,r,v,setv,rev; }T[N<<1];
      9 
     10 void build(int u,int L,int R) {
     11     T[u].l=L,T[u].r=R,T[u].setv=-1;T[u].rev=0;
     12     if(L==R) return ;
     13     int M=(L+R)>>1;
     14     build(u<<1,L,M); build(u<<1|1,M+1,R);
     15 }
     16 void pushdown(int u) {
     17     int lc=u<<1,rc=lc|1;
     18     if(T[u].l==T[u].r) {
     19         if(T[u].setv!=-1) T[u].v=T[u].setv;
     20         T[u].v^=T[u].rev; 
     21     }
     22     else {
     23         if(T[u].setv!=-1) {            //AT: set->rev=0 所以rev的执行顺序在set之后 
     24             T[lc].setv=T[rc].setv=T[u].setv;
     25             T[lc].rev=T[rc].rev=0;
     26         }
     27         T[lc].rev^=T[u].rev,T[rc].rev^=T[u].rev;
     28     }
     29     T[u].setv=-1, T[u].rev=0;
     30 }
     31 void update(int u,int L,int R,int x) {
     32     pushdown(u);
     33     if(L<=T[u].l && T[u].r<=R) {
     34         if(x==-1) T[u].rev^=1;
     35         else T[u].setv=x;
     36     }
     37     else {
     38         int M=(T[u].l+T[u].r)>>1;
     39         if(L<=M) update(u<<1,L,R,x);
     40         if(M<R) update(u<<1|1,L,R,x);
     41     }
     42 }
     43 int query(int u,int x) {
     44     pushdown(u);
     45     if(T[u].l==T[u].r) return T[u].v;
     46     else {
     47         int M=(T[u].l+T[u].r)>>1;
     48         if(x<=M) return query(u<<1,x);
     49         else return query(u<<1|1,x);
     50     }
     51 }
     52 void reverse(int u,int L,int R) { update(u,L,R,-1); }
     53 
     54 char s[2];
     55 void read(int& x) {
     56     char c=getchar(); int f=0; x=0;
     57     while(!isdigit(c)) { if(c=='(') f=1; c=getchar(); }
     58     while(isdigit(c))
     59         x=x*10+c-'0' , c=getchar();
     60     if(c==')') f=-1;
     61     x=x*2+f;
     62 }
     63 int main() {
     64     //freopen("in.in","r",stdin);
     65     //freopen("out.out","w",stdout);
     66     int n=65536*2+1;
     67     build(1,1,n);
     68     while(scanf("%s",s)==1) {
     69         int a,b;
     70         read(a),read(b);
     71         a+=2; b+=2;
     72         switch(s[0]) {
     73             case 'U':
     74                 update(1,a,b,1); break;
     75             case 'I':
     76                 update(1,1,a-1,0),update(1,b+1,n,0); break;
     77             case 'D':
     78                 update(1,a,b,0); break;
     79             case 'C':
     80                 update(1,1,a-1,0),update(1,b+1,n,0);
     81                 reverse(1,a,b); break;
     82             case 'S':
     83                 reverse(1,a,b); break;
     84         }
     85     }
     86     int f=-1,r=-1,flag=0;
     87     for(int i=1;i<=n;i++)
     88     {
     89         if(query(1,i)) { if(f==-1) f=i; r=i; }
     90         else {
     91             if(f!=-1) {
     92                 if(flag) putchar(' ');
     93                 else flag=1;
     94                 if(f&1) putchar('(');
     95                 else putchar('[');
     96                 printf("%d,%d",f/2-1,(r+1)/2-1);
     97                 if(r&1) putchar(')');
     98                 else putchar(']');
     99             }
    100             f=r=-1;
    101         }
    102     }
    103     if(!flag) puts("empty set");
    104     return 0;
    105 }
  • 相关阅读:
    全表扫描
    服务器信息表
    事务的丢失更新
    oracle core 概述
    oracle命中率模型计算
    性能量化之cpu
    一个sql导致temp表空间爆掉
    oracle稳定执行计划1
    oracle热点表online rename
    oracle构建一致性读
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5191237.html
Copyright © 2011-2022 走看看