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
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- 点击table行时,默认选中当前行中的复选框
- 小规模的两种题型
- 51Nod 1050 循环数组最大子段和 (最大字段和)
- hibernate的一级和二级缓存
- magento 根据url寻找要修改的文件
- SPOJ
- 关于myeclipse内置tomcat和使用自己安装的tomcat的区别
- 1. Two Sum
- Maven:mirror和repository区别
- CentOS下yum找不到某个包的问题解决方法
- voc2007数据集制作之批量修改文件夹JPEGImages中图片的名字
- 杭电oj---2010 水仙花数
- 《深入理解java虚拟机-高效并发》读书笔记
- UVA10154:Weights and Measures(类01背包)