按题意直接 每次输出 max(1,x),然后把(1,x)set为 max(1,x)+y。。。或者贪心也行。
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <queue> #include <map> //#include <set> #include <vector> using namespace std; __int64 max(__int64 a,__int64 b) {return a<b?b:a;} const __int64 N = 100005 ; __int64 maxx[4*N], set[4*N] ; void build(__int64 l,__int64 r,__int64 i) // 线段树的建立; { set[i]=0; //set[rt]=aa[++ok]; maxx[i]=0; // 用了lazy思想,提高了效率; if(l==r) return; __int64 mid=(l+r)>>1; build(l,mid,i<<1); build(mid+1,r,i<<1|1); } void pushDown(__int64 i, __int64 l, __int64 r) //把i节点的延迟标记传递到左右儿子节点 { if(set[i] != 0) { __int64 mid = (l + r) >> 1; set[i << 1] = set[i]; maxx[i << 1] = set[i]; //[l, mid]代表左儿子区间 set[i << 1 | 1] = set[i]; maxx[i << 1 | 1] = set[i]; //[mid + 1, r]代表右儿子区间 set[i] = 0; } } void update(__int64 i, __int64 l, __int64 r, __int64 ql, __int64 qr, __int64 val) //更新区间为qlqr,当前区间为l,r,代表当前区间和的节点为i,更新值为val, { if(l > qr || ql > r) //更新区间不在当前区间内 return ; if(l >= ql && r <= qr) //要更新的区间把当前区间完全包括,则把当前整个区间+val,然后返回上一层 { maxx[i] = val; set[i] = val; return ; } pushDown(i, l, r); //如果上面没reutrn 表示要往左右儿子区间查询,所以把延迟标记放下去 __int64 mid = (l + r) >> 1; update(i << 1, l, mid, ql, qr, val); update(i << 1 | 1, mid + 1, r, ql, qr, val); maxx[i] = max(maxx[i << 1] , maxx[i << 1 | 1]); } __int64 query(__int64 i, __int64 l, __int64 r, __int64 ql, __int64 qr) //查询区间为qlqr,当前区间为l,r,代表当前区间和的节点为i { if(l > qr || ql > r) return 0; if(l >= ql && r <= qr) return maxx[i]; pushDown(i, l, r); //同update __int64 mid =( l + r) >> 1; return max(query(i << 1, l, mid, ql, qr) ,query(i << 1 | 1, mid + 1, r, ql, qr)); //return (t1+t2*prime[mid-max(l,ql)+1])%mod;由于t1可能是属于return 0的情况,所以需要取max(l,ql),意义是取t1的有效长度 } int main() { int n; __int64 a,b,i; cin>>n; __int64 x,y; for (i=1;i<=n;i++) { scanf("%I64d",&x); update(1, 1, n, i, i,x); } int m; cin>>m; for( i = 1; i <= m; i++) { scanf("%I64d%I64d",&x,&y); __int64 ret=query(1, 1,n,1,x); printf("%I64d\n",ret); update(1, 1, n, 1, x,ret+y); } return 0; }