SPOJ

来源:互联网 发布:昆山cnc编程招聘信息 编辑:程序博客网 时间:2024/05/02 01:51
    发现一道数据结构,写好了,WA,改好了,WA,改好了,WA...    离线再用线段树维护的思路挺好想的,但是这个线段树求得MAX要包含历史所有版本中的,加上有lazy标记比较难维护。    最开始的思路是一个M1[]表示当前最大值,delta[]表示lazy标记,这部分正常做应该没问题。    然后再来一个M2[]表示M1[]的历史最大值。感觉没了...其实这样有的节点会出错...    考虑一个lazy标记了两次的节点,它向下传递信息的时候根本没有考虑第一个标记的情况...被第二次直接覆盖了...    so...    解决方法也不难,对delta[]记一个历史最大值Md[x],向下传递的时候一起传就好了。    更新M2[x]=max(M2[x],M1[x]-delta[x]+Md[x]);    这样就记录所有标记的情况,不会产生标记覆盖了。
#include <map>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define MAX(x,y) (x>y?x:y)typedef long long LL;inline LL read(){    LL 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;}const LL MAXN=100005;map<LL,LL> Q;LL n,m,a[MAXN],c[MAXN],M1[MAXN<<2],M2[MAXN<<2],Md[MAXN<<2],delta[MAXN<<2];struct Data{    LL l,r,o;    bool operator <(const Data &C)const{ return r<C.r||r==C.r&&l<C.l; }}B[MAXN];void Treeadd(LL x,LL l,LL r,LL ll,LL rr,LL k){    if (l==ll&&r==rr) {        delta[x]+=k; Md[x]=MAX(Md[x],delta[x]);        M1[x]+=k; M2[x]=MAX(M2[x],M1[x]-delta[x]+Md[x]);        return;    }    if (delta[x]!=0||Md[x]!=0) {        delta[x<<1]+=delta[x]; delta[x<<1|1]+=delta[x];        Md[x<<1]=MAX(Md[x<<1],delta[x<<1]); Md[x<<1|1]=MAX(Md[x<<1|1],delta[x<<1|1]);        Md[x<<1]=MAX(Md[x<<1],Md[x]+delta[x<<1]-delta[x]);        Md[x<<1|1]=MAX(Md[x<<1|1],Md[x]+delta[x<<1|1]-delta[x]);        M1[x<<1]+=delta[x]; M1[x<<1|1]+=delta[x]; delta[x]=Md[x]=0;        M2[x<<1]=MAX(M2[x<<1],M1[x<<1]-delta[x<<1]+Md[x<<1]);        M2[x<<1|1]=MAX(M2[x<<1|1],M1[x<<1|1]-delta[x<<1|1]+Md[x<<1|1]);    }    LL mid=(l+r)>>1;    if (ll>mid) Treeadd(x<<1|1,mid+1,r,ll,rr,k);    else if (mid>=rr) Treeadd(x<<1,l,mid,ll,rr,k);    else {        Treeadd(x<<1,l,mid,ll,mid,k);        Treeadd(x<<1|1,mid+1,r,mid+1,rr,k);    }    M1[x]=MAX(M1[x<<1],M1[x<<1|1]);    M2[x]=MAX(M2[x],M1[x]);}LL Treeask(LL x,LL l,LL r,LL ll,LL rr){    //cout<<x<<' '<<l<<' '<<r<<' '<<ll<<' '<<rr<<endl;    //cout<<x<<' '<<M1[x]<<' '<<M2[x]<<endl;    if (l==ll&&r==rr) return M2[x];    if (delta[x]!=0||Md[x]!=0) {        delta[x<<1]+=delta[x]; delta[x<<1|1]+=delta[x];        Md[x<<1]=MAX(Md[x<<1],delta[x<<1]); Md[x<<1|1]=MAX(Md[x<<1|1],delta[x<<1|1]);        Md[x<<1]=MAX(Md[x<<1],Md[x]+delta[x<<1]-delta[x]);        Md[x<<1|1]=MAX(Md[x<<1|1],Md[x]+delta[x<<1|1]-delta[x]);        M1[x<<1]+=delta[x]; M1[x<<1|1]+=delta[x]; delta[x]=Md[x]=0;        M2[x<<1]=MAX(M2[x<<1],M1[x<<1]-delta[x<<1]+Md[x<<1]);        M2[x<<1|1]=MAX(M2[x<<1|1],M1[x<<1|1]-delta[x<<1|1]+Md[x<<1|1]);    }    LL mid=(l+r)>>1;    if (ll>mid) return Treeask(x<<1|1,mid+1,r,ll,rr);    else if (mid>=rr) return Treeask(x<<1,l,mid,ll,rr);    else return MAX(Treeask(x<<1,l,mid,ll,mid),Treeask(x<<1|1,mid+1,r,mid+1,rr));}int main(){    LL i,j;    n=read();    for (i=1;i<=n;++i) a[i]=read();    m=read();    for (i=1;i<=m;++i) { B[i].l=read(); B[i].r=read(); B[i].o=i; }    sort(B+1,B+1+m);    //for (i=1;i<=m;++i) cout<<B[i].l<<' '<<B[i].r<<' '<<B[i].o<<endl;    Q.clear();    memset(M1,0,sizeof(M1));    memset(M2,0,sizeof(M2));    memset(delta,0,sizeof(delta));    for (i=j=1;i<=n;++i) {        Treeadd(1,1,n,Q[a[i]]+1,i,a[i]); Q[a[i]]=i;        for (;j<=m&&i==B[j].r;++j) c[B[j].o]=Treeask(1,1,n,B[j].l,B[j].r);        //cout<<Treeask(1,1,n,2,8)<<"lxsb"<<endl;    }    for (i=1;i<=m;++i) cout<<c[i]<<endl;    return 0;}/*10 -1 -2 -3 4 4 5 6 -6 -6 100 7 1 10 1 4 1 5 2 6 4 9 3 9 2 8*/
0 0
原创粉丝点击