BZOJ1251: 序列终结者
Posted wjyi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1251: 序列终结者相关的知识,希望对你有一定的参考价值。
题目大意:维护一种数据结构,支持下列操作:
1.将一个区间加上一个数
2.将一个区间翻转
3.询问一段区间的最大值
感受:傻叉题还敢说自己是序列终结者O__O "…
这道题写的时候还没修改我的splay模板,所以常数较大。。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int read(){ 4 int x=0,f=1;char ch=getchar(); 5 while(ch<\'0\'||ch>\'9\'){if(ch==\'-\')f=-1;ch=getchar();} 6 while(ch>=\'0\'&&ch<=\'9\'){x=x*10+ch-\'0\';ch=getchar();} 7 return x*f; 8 } 9 #define N 50005 10 int n,m,root,v[N],fa[N],sz[N],mx[N],tag[N],rev[N],ch[N][2]; 11 inline void pushup(int k){ 12 int l=ch[k][0],r=ch[k][1]; 13 mx[k]=max(mx[l],mx[r]); 14 mx[k]=max(mx[k],v[k]); 15 sz[k]=sz[l]+sz[r]+1; 16 } 17 void pushdown(int k){ 18 int l=ch[k][0],r=ch[k][1],t=tag[k]; 19 if(t){ 20 tag[k]=0; 21 if(l){tag[l]+=t;mx[l]+=t;v[l]+=t;} 22 if(r){tag[r]+=t;mx[r]+=t;v[r]+=t;} 23 } 24 if(rev[k]){ 25 rev[k]=0; 26 rev[l]^=1;rev[r]^=1; 27 swap(ch[k][0],ch[k][1]); 28 } 29 } 30 void Pushdown(int x){ 31 if(fa[x])Pushdown(fa[x]); 32 pushdown(x); 33 } 34 void rotate(int x,int &beto){ 35 int y=fa[x],t=ch[y][1]==x; 36 if(y!=beto)ch[fa[y]][ch[fa[y]][1]==y]=x;else beto=x; 37 fa[x]=fa[y];fa[y]=x; 38 fa[ch[x][!t]]=y; 39 ch[y][t]=ch[x][!t]; 40 ch[x][!t]=y; 41 pushup(y);pushup(x); 42 } 43 void splay(int x,int &beto){ 44 Pushdown(x); 45 while(x!=beto){ 46 int y=fa[x]; 47 if(y!=beto){ 48 if((ch[fa[y]][1]==y)==(ch[y][1]==x))rotate(y,beto); 49 else rotate(x,beto); 50 }rotate(x,beto); 51 } 52 } 53 void build(int l,int r,int f){ 54 int mid=l+r>>1; 55 fa[mid]=f;sz[mid]=1; 56 if(mid<f)ch[f][0]=mid;else ch[f][1]=mid; 57 if(l==r)return; 58 if(l<mid)build(l,mid-1,mid); 59 if(r>mid)build(mid+1,r,mid); 60 pushup(mid); 61 } 62 int find_k(int x,int k){ 63 pushdown(x); 64 if(sz[ch[x][0]]==k-1)return x; 65 if(sz[ch[x][0]]<k-1)return find_k(ch[x][1],k-sz[ch[x][0]]-1); 66 return find_k(ch[x][0],k); 67 } 68 int main(){ 69 n=read();m=read();n+=2; 70 mx[0]=-1e9; 71 build(1,n,0);root=(1+n)>>1; 72 for(int i=1;i<=m;i++){ 73 int t=read(),l=read(),r=read();r+=2; 74 l=find_k(root,l);r=find_k(root,r); 75 splay(l,root);splay(r,ch[l][1]); 76 int z=ch[r][0]; 77 if(t==1){ 78 int x=read(); 79 tag[z]+=x;v[z]+=x;mx[z]+=x; 80 } 81 if(t==2)rev[z]^=1; 82 if(t==3)printf("%d\\n",mx[z]); 83 } 84 return 0; 85 } 86
1251: 序列终结者
Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 3557 Solved: 1484
[Submit][Status][Discuss]
Description
网上有许多题,就是给定一个序列,要你支持几种操作:A、B、C、D。一看另一道题,又是一个序列 要支持几种操作:D、C、B、A。尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思。这道题目 就叫序列终结者吧。 【问题描述】 给定一个长度为N的序列,每个序列的元素是一个整数(废话)。要支持以下三种操作: 1. 将[L,R]这个区间内的所有数加上V。 2. 将[L,R]这个区间翻转,比如1 2 3 4变成4 3 2 1。 3. 求[L,R]这个区间中的最大值。 最开始所有元素都是0。
Input
第一行两个整数N,M。M为操作个数。 以下M行,每行最多四个整数,依次为K,L,R,V。K表示是第几种操作,如果不是第1种操作则K后面只有两个数。
Output
对于每个第3种操作,给出正确的回答。
Sample Input
4 4
1 1 3 2
1 2 4 -1
2 1 3
3 2 4
1 1 3 2
1 2 4 -1
2 1 3
3 2 4
Sample Output
2
【数据范围】
N<=50000,M<=100000。
【数据范围】
N<=50000,M<=100000。
以上是关于BZOJ1251: 序列终结者的主要内容,如果未能解决你的问题,请参考以下文章