您的位置:首页 > 其它

BZOJ1251: 序列终结者

2016-06-23 20:44 260 查看
题目大意:维护一种数据结构,支持下列操作:

1.将一个区间加上一个数

2.将一个区间翻转

3.询问一段区间的最大值

感受:傻叉题还敢说自己是序列终结者O__O "…

这道题写的时候还没修改我的splay模板,所以常数较大。。

#include<bits/stdc++.h>
using namespace std;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
#define N 50005
int n,m,root,v
,fa
,sz
,mx
,tag
,rev
,ch
[2];
inline void pushup(int k){
int l=ch[k][0],r=ch[k][1];
mx[k]=max(mx[l],mx[r]);
mx[k]=max(mx[k],v[k]);
sz[k]=sz[l]+sz[r]+1;
}
void pushdown(int k){
int l=ch[k][0],r=ch[k][1],t=tag[k];
if(t){
tag[k]=0;
if(l){tag[l]+=t;mx[l]+=t;v[l]+=t;}
if(r){tag[r]+=t;mx[r]+=t;v[r]+=t;}
}
if(rev[k]){
rev[k]=0;
rev[l]^=1;rev[r]^=1;
swap(ch[k][0],ch[k][1]);
}
}
void Pushdown(int x){
if(fa[x])Pushdown(fa[x]);
pushdown(x);
}
void rotate(int x,int &beto){
int y=fa[x],t=ch[y][1]==x;
if(y!=beto)ch[fa[y]][ch[fa[y]][1]==y]=x;else beto=x;
fa[x]=fa[y];fa[y]=x;
fa[ch[x][!t]]=y;
ch[y][t]=ch[x][!t];
ch[x][!t]=y;
pushup(y);pushup(x);
}
void splay(int x,int &beto){
Pushdown(x);
while(x!=beto){
int y=fa[x];
if(y!=beto){
if((ch[fa[y]][1]==y)==(ch[y][1]==x))rotate(y,beto);
else rotate(x,beto);
}rotate(x,beto);
}
}
void build(int l,int r,int f){
int mid=l+r>>1;
fa[mid]=f;sz[mid]=1;
if(mid<f)ch[f][0]=mid;else ch[f][1]=mid;
if(l==r)return;
if(l<mid)build(l,mid-1,mid);
if(r>mid)build(mid+1,r,mid);
pushup(mid);
}
int find_k(int x,int k){
pushdown(x);
if(sz[ch[x][0]]==k-1)return x;
if(sz[ch[x][0]]<k-1)return find_k(ch[x][1],k-sz[ch[x][0]]-1);
return find_k(ch[x][0],k);
}
int main(){
n=read();m=read();n+=2;
mx[0]=-1e9;
build(1,n,0);root=(1+n)>>1;
for(int i=1;i<=m;i++){
int t=read(),l=read(),r=read();r+=2;
l=find_k(root,l);r=find_k(root,r);
splay(l,root);splay(r,ch[l][1]);
int z=ch[r][0];
if(t==1){
int x=read();
tag[z]+=x;v[z]+=x;mx[z]+=x;
}
if(t==2)rev[z]^=1;
if(t==3)printf("%d\n",mx[z]);
}
return 0;
}


View Code

1251: 序列终结者

Time Limit: 20 Sec Memory Limit: 162 MB
Submit: 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

Sample Output

2

【数据范围】

N<=50000,M<=100000。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: