您的位置:首页 > 产品设计 > UI/UE

hdu 5828 Rikka with Sequence 【线段树+优化】

2016-08-12 18:48 429 查看
链接:http://acm.hdu.edu.cn/showproblem.php?pid=5828

题意:给你n个数,q个操作,操作k,l,r,k=1时 区间[l,r]每个数加x,k=2时,区间[l,r]每个数开平方,k=3时,求区间[l,r]的和。

分析:我们知道一个数多次开平方会变成1,但是这里的1操作会使这个数的值增大,所以直接判断一个区间是否为1肯定超时。

官方题解加了个优化,就是判断一个区间内是否为一个值,因为有些区间在操作1和2下会变成一个值。

但是有一组数据把标程hack了:10万个2,3,2,3,2,3.......,10万个操作 加6,开根。

这样每个数相等的区间大小就为1了,标程T了。

我们来考虑这种数据,如果一个区间的极差>1,那么经过多次1,2操作后,最终这个区间的极差要么是0,要么是1,那么我们只要维护极差<=1的区间就好了。

后来也T了很久。。。要用读入优化和输入加到build里,G++提交。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 100010
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CLRS(a,b,Size) memset((a),(b),sizeof((a[0]))*(Size+1))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int read() {
char c=getchar();
int re=0,f=1;
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') {re=re*10+c-'0';c=getchar();}
return re*f;
}
int a[Mn];
ll sum[Mn*4];
ll maxx[Mn*4],minn[Mn*4];
ll maxNum[Mn*4],minNum[Mn*4];
ll all[Mn*4];
ll lazy[Mn*4];
void pushUp(int u) {
sum[u]=sum[ul]+sum[ur];
maxx[u]=max(maxx[ul],maxx[ur]);
minn[u]=min(minn[ul],minn[ur]);
maxNum[u]=minNum[u]=0;
if(maxx[u]==maxx[ul]) maxNum[u]+=maxNum[ul];
if(maxx[u]==maxx[ur]) maxNum[u]+=maxNum[ur];
if(minn[u]==minn[ul]) minNum[u]+=minNum[ul];
if(minn[u]==minn[ur]) minNum[u]+=minNum[ur];
}
void pushDown(int u,int l,int r) {
if(all[u]) {
int mid=(l+r)>>1;
all[ul]=all[ur]=all[u];
sum[ul]=all[u]*(mid-l+1);
sum[ur]=all[u]*(r-mid);
maxx[ul]=maxx[ur]=minn[ul]=minn[ur]=all[u];
maxNum[ul]=minNum[ul]=mid-l+1;
maxNum[ur]=minNum[ur]=r-mid;
lazy[ul]=lazy[ur]=0;
all[u]=0;
}
if(lazy[u]) {
int mid=(l+r)>>1;
lazy[ul]+=lazy[u];lazy[ur]+=lazy[u];
sum[ul]+=lazy[u]*(mid-l+1);
sum[ur]+=lazy[u]*(r-mid);
maxx[ul]+=lazy[u];minn[ul]+=lazy[u];
maxx[ur]+=lazy[u];minn[ur]+=lazy[u];
lazy[u]=0;
}
}
void build(int l,int r,int u) {
all[u]=lazy[u]=maxx[u]=minn[u]=sum[u]=0;
if(l==r) {
maxx[u]=minn[u]=sum[u]=read();
maxNum[u]=minNum[u]=1;
return ;
}
int mid=(l+r)>>1;
build(l,mid,ul);
build(mid+1,r,ur);
pushUp(u);
}
int s,t;
void add(int l,int r,int u,int x) {
if(s<=l&&t>=r) {
sum[u]+=(ll)x*(r-l+1);
minn[u]+=x;
maxx[u]+=x;
lazy[u]+=x;
return ;
}
pushDown(u,l,r);
int mid=(l+r)>>1;
if(s<=mid) add(l,mid,ul,x);
if(t>mid) add(mid+1,r,ur,x);
pushUp(u);
}
void Sqrt(int l,int r,int u) {
if(s<=l&&t>=r&&(maxx[u]-minn[u]<=1)) {
if(maxx[u]==1) return ;
int x=maxx[u];
if(maxx[u]==minn[u]) {
minn[u]=maxx[u]=floor(sqrt(x));
lazy[u]+=maxx[u]-x;
sum[u]=maxx[u]*(r-l+1);
return ;
} else if(maxx[u]-minn[u]==1){
maxx[u]=floor(sqrt(maxx[u]));
minn[u]=floor(sqrt(minn[u]));
if(maxx[u]==minn[u]) {
maxNum[u]=minNum[u]=r-l+1;
lazy[u]=0;
all[u]=maxx[u];
sum[u]=maxx[u]*maxNum[u];
} else if(maxx[u]-minn[u]==1) {
lazy[u]+=maxx[u]-x;
sum[u]=maxx[u]*maxNum[u]+minn[u]*minNum[u];
}
return ;
}
return ;
}
pushDown(u,l,r);
int mid=(l+r)>>1;
if(s<=mid) Sqrt(l,mid,ul);
if(t>mid) Sqrt(mid+1,r,ur);
pushUp(u);
}
ll query(int l,int r,int u) {
if(s<=l&&t>=r) {
return sum[u];
}
pushDown(u,l,r);
int mid=(l+r)>>1;
ll re=0;
if(s<=mid) re+=query(l,mid,ul);
if(t>mid) re+=query(mid+1,r,ur);
return re;
}
int main() {
int T=read(),k;
while(T--) {
int n=read(),m=read();
build(1,n,1);
while(m--) {
k=read(),s=read(),t=read();
if(k==1) {
int x=read();
add(1,n,1,x);
} else if(k==2){
Sqrt(1,n,1);
} else {
printf("%I64d\n",query(1,n,1));
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: