线段树好题
因为题目中相同的只算一次,我们可以联想到HH的项链,于是考虑离线的做法
先把所有的询问按$r$排序,然后每一次不断将$a[r]$加入线段树
线段树上维护四个值,$sum,hix,sumtag,hixtag$,分别代表当前节点的值,节点历史上的最大值,当前的增加标记,历史上最大的增加标记
然后pushdown的过程可以看代码,还是比较清楚的
考虑怎么添加元素,设序列中上一个与$i$相等的数的位置是$Pre[i]$,那么就把区间$[Pre[i],i]$加$a[i]$即可
查询的话只要查$[l,r]$的$hix$即可
除了pushdown有点烦其他都还好
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 #define ls (p<<1) 6 #define rs (p<<1|1) 7 #define ll long long 8 using namespace std; 9 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 10 char buf[1<<21],*p1=buf,*p2=buf; 11 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} 12 ll read(){ 13 #define num ch-'0' 14 char ch;bool flag=0;ll res; 15 while(!isdigit(ch=getc())) 16 (ch=='-')&&(flag=true); 17 for(res=num;isdigit(ch=getc());res=res*10+num); 18 (flag)&&(res=-res); 19 #undef num 20 return res; 21 } 22 char sr[1<<21],z[20];int C=-1,Z; 23 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} 24 void print(ll x){ 25 if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x; 26 while(z[++Z]=x%10+48,x/=10); 27 while(sr[++C]=z[Z],--Z);sr[++C]='\n'; 28 } 29 const int N=1e5+5; 30 struct node{ 31 ll sum,hix,stag,htag; 32 node(){sum=hix=stag=htag=0;} 33 inline node operator +(node b){ 34 node res; 35 res.sum=max(sum,b.sum),res.hix=max(hix,b.hix); 36 return res; 37 } 38 }b[N<<2]; 39 struct Q{ 40 int l,r,id; 41 inline bool operator <(const Q b)const 42 {return r<b.r;} 43 }q[N]; 44 int n,m,cur[N*2],Pre[N],ql,qr;ll a[N],ans[N],k; 45 inline void upd(int p){b[p]=b[ls]+b[rs];} 46 void pd(int p){ 47 b[ls].hix=max(b[ls].hix,b[ls].sum+b[p].htag); 48 b[rs].hix=max(b[rs].hix,b[rs].sum+b[p].htag); 49 b[ls].sum+=b[p].stag,b[rs].sum+=b[p].stag; 50 b[ls].htag=max(b[ls].htag,b[ls].stag+b[p].htag); 51 b[rs].htag=max(b[rs].htag,b[rs].stag+b[p].htag); 52 b[ls].stag+=b[p].stag,b[rs].stag+=b[p].stag; 53 b[p].stag=b[p].htag=0; 54 } 55 void update(int p,int l,int r){ 56 if(ql<=l&&qr>=r){ 57 b[p].sum+=k,cmax(b[p].hix,b[p].sum); 58 b[p].stag+=k,cmax(b[p].htag,b[p].stag); 59 return; 60 } 61 pd(p);int mid=(l+r)>>1; 62 if(ql<=mid) update(ls,l,mid); 63 if(qr>mid) update(rs,mid+1,r); 64 upd(p); 65 } 66 node query(int p,int l,int r){ 67 if(ql<=l&&qr>=r) return b[p]; 68 pd(p);int mid=(l+r)>>1; 69 if(ql>mid) return query(rs,mid+1,r); 70 else if(qr<=mid) return query(ls,l,mid); 71 else return query(ls,l,mid)+query(rs,mid+1,r); 72 } 73 int main(){ 74 // freopen("testdata.in","r",stdin); 75 n=read(); 76 for(int i=1;i<=n;++i) 77 a[i]=read(),Pre[i]=cur[a[i]+(int)1e5],cur[a[i]+(int)1e5]=i; 78 m=read(); 79 for(int i=1;i<=m;++i) 80 q[i].l=read(),q[i].r=read(),q[i].id=i; 81 sort(q+1,q+1+m); 82 for(int i=1,j=1;i<=n&&j<=m;++i){ 83 ql=Pre[i]+1,qr=i,k=a[i];update(1,1,n); 84 for(;j<=m&&q[j].r<=i;++j){ 85 ql=q[j].l,qr=q[j].r; 86 ans[q[j].id]=query(1,1,n).hix; 87 } 88 } 89 for(int i=1;i<=m;++i) print(ans[i]); 90 return Ot(),0; 91 }