【分块】bzoj3226 [Sdoi2008]校门外的区间

题解见 : http://blog.csdn.net/iamzky/article/details/41088151

ORZ ZKY

2个懒标记:是否翻转,覆盖成了什么。

怎么处理一个块上有两个标记的情况呢?

若该块原来没有任何标记,或要打的标记和原本的标记种类相同,则直接打上标记;

若已有翻转标记,再覆盖时则先清除翻转标记,再打上覆盖标记;

若已有覆盖标记,再翻转时,则直接将覆盖标记取反。

So 某个块上同时只会有1个标记。

P.S.分块此题挺快的……

  1 #include<cstdio>
  2 #include<cstring>
  3 using namespace std;
  4 #define sz 370
  5 const int n=131070;
  6 char op[1],cl,cr;
  7 int x,y,num[132000],l[sz],r[sz],cov[sz],sum;
  8 bool a[132000],spin[sz],goal;
  9 void makeblock()
 10 {
 11     for(sum=1;sum*sz<n;++sum)
 12       {
 13           l[sum]=r[sum-1]+1; r[sum]=sum*sz;
 14           for(int i=l[sum];i<=r[sum];++i) num[i]=sum;
 15       }
 16     l[sum]=r[sum-1]+1; r[sum]=n;
 17     for(int i=l[sum];i<=r[sum];++i) num[i]=sum;
 18     memset(cov,-1,sizeof(cov));
 19 }
 20 void pushdown(const int &p)
 21 {
 22     if(cov[p]!=-1)
 23       {
 24         for(int i=l[p];i<=r[p];i++) a[i]=cov[p];
 25         cov[p]=-1;
 26       }
 27     else if(spin[p])
 28       {
 29         for(int i=l[p];i<=r[p];i++) a[i]^=1;
 30         spin[p]=0;
 31       }
 32 }
 33 void update(const int &L,const int &R,const bool &sym)
 34 {
 35     pushdown(num[L]); pushdown(num[R]);
 36     if(num[L]==num[R]) {for(int i=L;i<=R;++i) a[i]=sym;}
 37     else
 38       {
 39           for(int i=L;i<=r[num[L]];++i) a[i]=sym;
 40           for(int i=l[num[R]];i<=R;++i) a[i]=sym;
 41           for(int i=num[L]+1;i<num[R];++i) {spin[i]=0; cov[i]=sym;}
 42       }
 43 }
 44 void rotate(const int &L,const int &R)
 45 {
 46     pushdown(num[L]); pushdown(num[R]);
 47     if(num[L]==num[R]) {for(int i=L;i<=R;++i) a[i]^=1;}
 48     else
 49       {
 50           for(int i=L;i<=r[num[L]];++i) a[i]^=1;
 51           for(int i=l[num[R]];i<=R;++i) a[i]^=1;
 52           for(int i=num[L]+1;i<num[R];++i)
 53             if(cov[i]==-1) spin[i]^=1;
 54             else cov[i]^=1;
 55       }
 56 }
 57 int Ma(const int &v,const char &c)
 58 {
 59     if(c==‘[‘||c==‘]‘) return (v<<1);
 60     else if(c==‘(‘) return (v<<1)+1;
 61     else return (v<<1)-1;
 62 }
 63 int main()
 64 {
 65     makeblock();
 66     while(scanf("%s %c%d,%d%c",op,&cl,&x,&y,&cr)!=EOF)
 67       {
 68           if(op[0]==‘U‘) update(Ma(x,cl),Ma(y,cr),1);
 69           else if(op[0]==‘I‘)
 70             {
 71                 if(x) update(0,Ma(x,cl)-1,0);
 72                 if(y!=65535) update(Ma(y,cr)+1,65535<<1,0);
 73             }
 74           else if(op[0]==‘D‘) update(Ma(x,cl),Ma(y,cr),0);
 75           else if(op[0]==‘C‘)
 76             {
 77                 rotate(Ma(x,cl),Ma(y,cr));
 78                 if(x) update(0,Ma(x,cl)-1,0);
 79                 if(y!=65535) update(Ma(y,cr)+1,65535<<1,0);
 80             }
 81           else rotate(Ma(x,cl),Ma(y,cr));
 82       }
 83     int head=0;
 84     for(int i=1;i<=sum;++i) pushdown(i);
 85     for(int i=0;i<=n;++i)
 86       {
 87           if(((!i) && a[i]) || (a[i] && (!a[i-1]))) head=i;
 88         if((i==n && a[i]) || (a[i] && (!a[i+1])))
 89           {
 90               goal=1;
 91               if(head&1) putchar(‘(‘);
 92               else putchar(‘[‘);
 93               printf("%d,",head>>1);
 94               if(i&1) {printf("%d",i+1>>1); putchar(‘)‘);}
 95               else {printf("%d",i>>1); putchar(‘]‘);}
 96               putchar(‘ ‘);
 97           }
 98       }
 99     if(!goal) puts("empty set");
100     return 0;
101 }
时间: 2024-10-10 04:31:31

【分块】bzoj3226 [Sdoi2008]校门外的区间的相关文章

BZOJ3226[Sdoi2008]校门外的区间 题解

题目大意: 有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) 思路: 每个数之间加入一个数,就像这样2 2.5 3 3.5 4 [2,3) -> [2,2.5] (3,4] ->

bzoj3226: [Sdoi2008]校门外的区间 线段树

题比较有趣,输入输出比较麻烦. 每个点拆成两个,线段树维护.(这题难点真的在输入输出) #include<bits/stdc++.h> #define N (1<<17) #define M (l+r>>1) #define P (k<<1) #define S (k<<1|1) #define K l,r,k #define L l,M,P #define R M+1,r,S #define Z int l=0,int r=N,int k=1

[SDOI2008]校门外的区间

Description [SDOI2008]校门外的区间 ### Solution 两个整数之间再建一个点(如\(1\)和\(2\)之间再建一个\(1.5\)这个点),然后把开区间变成\(\pm1.5\)的闭区间 如\((1,5)\)变成\([1.5,4.5]\) \(U\) 区间涂色 \(I\) 两侧区间涂\(0\) \(D\) 区间涂\(0\) \(C\) 两侧涂\(0\),中间取反 \(S\) 区间取反 Code 原文地址:https://www.cnblogs.com/Agakiss/p

BZOJ 3226 [SDOI2008]校门外的区间

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3226 题意: 给定一个空集合S,维护五种集合与集合的操作,将最终得到的集合输出. 对于集合S和T,操作包括S=S∪T.S=S∩T.S=S?T.S=T?S.S=S?T. 每次的操作是给定一个T,并保证T表示的元素是一段连续的区间,可能开可能闭,区间端点均为整数. 最终输出的集合S要按升序输出每个连续的区间. 操作数≤70000,集合的数字∈[0,65535]. 题解: 考虑到区间的端点均为整数

3226: [Sdoi2008]校门外的区间

链接 思路 bug漫天飞... 维护一颗线段树,支持区间赋值,和区间异或.因为会处理到一些方括号还是圆括号的问题,所以对于每一个下标都乘2,假设中间有一个.5即可,都变成了方括号,输出在处理一下. U  [l,r]赋值为1 I   [0,l-1],[r+1,n]赋值为0 D [l,r]区间涂0 C [0,l-1],[r+1,n]赋值为0,[l,r]区间异或 S [l,r]区间异或 bug列表:乘2后从0开始,因为0*2=0,0.5*2=1,zz的居然是从2开始的.. 读入的区间并不都是一位数..

[bzoj 3226]校门外的区间

题意 输出最后的集合   题解 校门外的树会做吧 区间知道是什么东西吧 校门外的区间会做了吧 昨天做个大线段树没做出来,今天做个小线段树压压惊 py一下输入数据,然后操作变成: U 区间涂1 I 两侧区间涂0 D 区间涂0 C 两侧涂0,中间取反 S 区间取反 #include<map> #include<stack> #include<queue> #include<cstdio> #include<string> #include<ve

TyvjOJ题目 P1473 校门外的树3(线段树区间染色种类数不覆盖)

P1473 校门外的树3 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的-- 如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作: K=1,读入l,r表示在l~r之间种上的一种树 K=2,读入l,r表示询问l~r之间能见到多少种树 (l,r>0) 输入格式 第一行n,m表示道路总长为n,共有m个操作 接下来m行为m个操作 输出格式 对于每个k=

C语言 &#183; 校门外的树

算法提高 校门外的树 时间限制:1.0s   内存限制:256.0MB 问题描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0,1,2,--,L,都种有一棵树. 由于马路上有一些区域要用来建地铁.这些区域用它们在数轴上的起始点和终止点表示.已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分.现在要把这些区域中的树(包括区域端点处的两棵树)移走.你的任务是计算

vijos P1448 校门外的树

描述 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:K=1,K=1,读入l.r表示在区间[l,r]中种上一种树,每次操作种的树的种类都不同K=2,读入l,r表示询问l~r之间能见到多少种树(l,r>0) 输入格式 第一行n,m表示道路总长为n,共有m个操作接下来m行为m个操作 输出格式 对于每个k=2输出一个答案 提示 范围:20%的数据保证,n,m<=10060%的数据保证