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

来源:互联网 发布:金蝶软件精斗云 编辑:程序博客网 时间:2024/05/29 14:52

链接: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)|1using 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;}


0 0
原创粉丝点击