解题:SCOI 2010 序列操作

题面

线段树......模板题(雾?

然而两种标记会互相影响,必须保证每次只放一个(不然就不知道怎么放了),具体的影响就是:

翻转标记会使得覆盖标记一起翻转,下放的时候就是各种swap

覆盖标记会抹掉翻转标记,下放的时候好像挺正常的

然后就是码码码+细节

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 const int N=100005;
  6 struct a{int ll,rr,vv;};
  7 int val[4*N],last[4*N][2],lst[4*N][2],rst[4*N][2];
  8 int num[N],laz1[4*N],laz2[4*N];
  9 int n,m,t1,t2,t3;
 10 void pushup(int nde,int l,int r)
 11 {
 12     int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
 13     val[nde]=val[ls]+val[rs];
 14     //value
 15     lst[nde][1]=(last[ls][1]==mid-l+1)?last[ls][1]+lst[rs][1]:lst[ls][1];
 16     rst[nde][1]=(last[rs][1]==r-mid)?last[rs][1]+rst[ls][1]:rst[rs][1];
 17     last[nde][1]=max(rst[ls][1]+lst[rs][1],max(last[ls][1],last[rs][1]));
 18     //longest continuing one
 19     lst[nde][0]=(last[ls][0]==mid-l+1)?last[ls][0]+lst[rs][0]:lst[ls][0];
 20     rst[nde][0]=(last[rs][0]==r-mid)?last[rs][0]+rst[ls][0]:rst[rs][0];
 21     last[nde][0]=max(rst[ls][0]+lst[rs][0],max(last[ls][0],last[rs][0]));
 22     //longest continuing zero
 23 }
 24 void create(int nde,int l,int r)
 25 {
 26     if(l==r)
 27     {
 28         last[nde][0]=lst[nde][0]=rst[nde][0]=(num[l]^1);
 29         val[nde]=last[nde][1]=lst[nde][1]=rst[nde][1]=num[l];
 30     }
 31     else
 32     {
 33         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
 34         create(ls,l,mid),create(rs,mid+1,r);
 35         pushup(nde,l,r);
 36     }
 37 }
 38 void release(int nde,int l,int r)
 39 {
 40     int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
 41     if(laz2[nde])
 42     {
 43         if(~laz1[ls]) laz1[ls]^=1; else laz2[ls]^=1;
 44         if(~laz1[rs]) laz1[rs]^=1; else laz2[rs]^=1;
 45         val[ls]=(mid-l+1)-val[ls],val[rs]=(r-mid)-val[rs];
 46         //reversing
 47         swap(last[ls][0],last[ls][1]),swap(last[rs][0],last[rs][1]);
 48         swap(lst[ls][0],lst[ls][1]),swap(lst[rs][0],lst[rs][1]);
 49         swap(rst[ls][0],rst[ls][1]),swap(rst[rs][0],rst[rs][1]);
 50         //a lot of swaps......
 51         laz2[nde]=0;
 52         //refresh
 53     }
 54     //release the lazy tag of intervals reversing
 55     else if(~laz1[nde])
 56     {
 57         laz1[ls]=laz1[nde],laz1[rs]=laz1[nde],laz2[ls]=0,laz2[rs]=0;
 58         //to the left/right son
 59         val[ls]=last[ls][1]=lst[ls][1]=rst[ls][1]=(mid-l+1)*laz1[nde];
 60         val[rs]=last[rs][1]=lst[rs][1]=rst[rs][1]=(r-mid)*laz1[nde];
 61         //longest continuing one
 62         last[ls][0]=lst[ls][0]=rst[ls][0]=(mid-l+1)*(laz1[nde]^1);
 63         last[rs][0]=lst[rs][0]=rst[rs][0]=(r-mid)*(laz1[nde]^1);
 64         //longest continuing zero
 65         laz1[nde]=-1;
 66         //refresh
 67     }
 68     //release the lazy tag of intervals covering
 69 }
 70 void Change(int nde,int l,int r,int nl,int nr,int task)
 71 {
 72     if(l>nr||r<nl)
 73         return ;
 74     else if(l>=nl&&r<=nr)
 75     {
 76         last[nde][0]=lst[nde][0]=rst[nde][0]=(task^1)*(r-l+1);
 77         val[nde]=last[nde][1]=lst[nde][1]=rst[nde][1]=task*(r-l+1);
 78         laz1[nde]=task,laz2[nde]=0;
 79     }
 80     else
 81     {
 82         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; release(nde,l,r);
 83         Change(ls,l,mid,nl,nr,task),Change(rs,mid+1,r,nl,nr,task);
 84         pushup(nde,l,r);
 85     }
 86 }
 87 void Reverse(int nde,int l,int r,int nl,int nr)
 88 {
 89     if(l>nr||r<nl)
 90         return ;
 91     else if(l>=nl&&r<=nr)
 92     {
 93         val[nde]=(r-l+1)-val[nde],swap(last[nde][0],last[nde][1]);
 94         swap(lst[nde][0],lst[nde][1]),swap(rst[nde][0],rst[nde][1]);
 95         if(~laz1[nde]) laz1[nde]^=1; else laz2[nde]^=1;
 96     }
 97     else
 98     {
 99         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; release(nde,l,r);
100         Reverse(ls,l,mid,nl,nr),Reverse(rs,mid+1,r,nl,nr); pushup(nde,l,r);
101     }
102 }
103 int Vquery(int nde,int l,int r,int nl,int nr)
104 {
105     if(l>nr||r<nl)
106         return 0;
107     else if(l>=nl&&r<=nr)
108         return val[nde];
109     else
110     {
111         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; release(nde,l,r);
112         return Vquery(ls,l,mid,nl,nr)+Vquery(rs,mid+1,r,nl,nr);
113     }
114 }
115 a Lquery(int nde,int l,int r,int nl,int nr)
116 {
117     if(l>=nl&&r<=nr)
118         return (a){lst[nde][1],rst[nde][1],last[nde][1]};
119     else
120     {
121         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; release(nde,l,r);
122         if(nr<=mid) return Lquery(ls,l,mid,nl,nr);
123         if(nl>mid) return Lquery(rs,mid+1,r,nl,nr);
124         a Q1=Lquery(ls,l,mid,nl,nr),Q2=Lquery(rs,mid+1,r,nl,nr),ret;
125         ret.vv=max(max(Q1.vv,Q2.vv),Q1.rr+Q2.ll);
126         ret.ll=(Q1.vv==(mid-l+1))?Q1.vv+Q2.ll:Q1.ll;
127         ret.rr=(Q2.vv==(r-mid))?Q2.vv+Q1.rr:Q2.rr;
128         return ret;
129     }
130 }
131 int main ()
132 {
133     scanf("%d%d",&n,&m);
134     for(int i=1;i<=n;i++)
135         scanf("%d",&num[i]);
136     create(1,1,n);
137     memset(laz1,-1,sizeof laz1);
138     for(int i=1;i<=m;i++)
139     {
140         scanf("%d%d%d",&t1,&t2,&t3),t2++,t3++;
141         if(!t1) Change(1,1,n,t2,t3,0);
142         else if(t1==1) Change(1,1,n,t2,t3,1);
143         else if(t1==2) Reverse(1,1,n,t2,t3);
144         else if(t1==3) printf("%d\n",Vquery(1,1,n,t2,t3));
145         else printf("%d\n",Lquery(1,1,n,t2,t3).vv);
146     }
147     return 0;
148 }

原文地址:https://www.cnblogs.com/ydnhaha/p/9729664.html

时间: 2024-08-30 04:58:56

解题:SCOI 2010 序列操作的相关文章

BZOJ 1858 SCOI 2010 序列操作

题目大意:维护一种01数据结构,它可以: 1.把一段区间变成0. 2.把一段区间变成1. 3.把一段区间取反. 4.查询一段区间内1的个数. 5.查询一段区间内连续的1的个数. 思路:一眼看去Splay和线段树都可以,看起来好像Splay维护起来好弄一点,就没怎么想写了Splay.写完之后才发现Splay维护的时候边界值根本没法弄(可能是我写的麻烦),就又重写线段树.啊啊啊啊现在整个人都发要疯了.. 其实线段树和Splay的思想是一样的,需要维护一下几个东西: 1.一段区间内,左边开始连续0的个

序列操作

2421 序列操作 http://codevs.cn/problem/2421/ 2010年省队选拔赛四川  题目等级 : 大师 Master 题目描述 Description lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[a,b]区间内的所有数全部取反,也就是说把所有的0变成1,把所有的1变成0 3

bzoj 1858: [Scoi2010] 序列操作 题解

[原题] 1858: [Scoi2010]序列操作 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 1031  Solved: 529 [Submit][Status] Description lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[a,b]区间内

Python基础--通用序列操作

Python 继续 Python包含6种内建的序列,各自是:列表.元组.字符串.Unicode字符串.buffer对象和xrange对象.我们将逐步进行介绍. 今天主要介绍一下通用序列操作.放之四海而皆准. 1 索引 全部程序猿都知道,索引下标从零開始.Python也是这样, 索引0指向序列中第一个元素. 可是与C++相比.Python又添加了负索引.最后1个元素的索引是-1,从右至左是-2.-3 - 字符串字面值直接能够索引: >>>'Hello'[1] e 2 分片 分片通过冒号隔开

1858: [Scoi2010]序列操作

1858: [Scoi2010]序列操作 Description lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[a,b]区间内的所有数全部取反,也就是说把所有的0变成1,把所有的1变成0 3 a b 询问[a, b]区间内总共有多少个1 4 a b 询问[a, b]区间内最多有多少个连续的1 对于每一

[python基础(一)]序列操作基础

一.python的数据结构 容器:包含其他对象的任意对象. 包括:序列(例如列表,元组),映射(例如字典),集合等.主要是序列和映射. 二.序列操作 索引,分片,加,乘,检查某元素是否是该序列成员.此外,计算序列长度,寻找最大,最下元素. 1.索引 正数:从0开始,左至右: 负数:从-1开始,有至左 2.分片 两个索引作为边界,第一个索引元素包含在分片内,第二个不包含. A='123456789' Print A[2:5] '345' 3.序列相加 条件:序列的类型相同 4.乘法 5.成员资格

OpenCV视频序列操作基础

 从视频序列中抓取一帧 OpenCV支持从摄像头或视频文件(AVI)中抓取图像. 从摄像头获取初始化: CvCapture* capture = cvCaptureFromCAM(0); // capture from video device #0 从视频文件获取初始化: CvCapture* capture = cvCaptureFromAVI("infile.avi"); 抓取帧: IplImage* img = 0; if(!cvGrabFrame(capture)){  

【BZOJ-1858】序列操作 线段树

1858: [Scoi2010]序列操作 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1961  Solved: 991[Submit][Status][Discuss] Description lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[a,b]区

【BZOJ 1858】 [Scoi2010]序列操作

1858: [Scoi2010]序列操作 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 1368 Solved: 712 [Submit][Status][Discuss] Description lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[a,b]区