题目链接在本地
这道题如果按照题目意思去算c_i的话每一步都会是 O(n) 的复杂度,而且并不知道每一步的操作对后续的影响是什么,很显然不能这么做
这种情况下我们要考虑到要将c_i化成一个和 1...i 或者 i...n 有关的式子(i...n的情况可以用1...n减去1...i-1来解决),这样才能用数据结构的方法去解决
将c_x展开来看的话,我们可以发现c_x=max(a_i+b_i+b_(i+1)+b_(i+2)+...+b_x) (i=1...x) 到这一步已经有些眉目了,我们可以建立一棵最大值线段树,但是我们发现这个b_i的求和还是有些难度的,仔细观察可以发现是上一段说到的 i...n 的情况,所以式子可以化简为 c_x=(b_1+...+b_x) + max (a_i - (b_1+...+b_i)) (i=1...x) 这样我们就把 i...n 的情况转化为1...i的情况,就可以用树状数组的方法比较容易的求出来。
上上段说到的这个简化提取通项的思想是非常重要的,不仅是在数据结构中有用,因为如果不简化取通项,永远只能关注到前后两项,根本找不出思路,这种求通项的思想在很多问题中都具有广泛应用。
1 #include "bits/stdc++.h" 2 #define lson rt<<1,l,m 3 #define rson rt<<1|1,m+1,r 4 using namespace std; 5 typedef long long LL; 6 const int MAX=2e5+5; 7 LL n,cas; 8 LL a[MAX],b[MAX],s[MAX]; 9 LL t[MAX<<2],la[MAX<<2]; 10 void update(LL x,LL y){for (;x<=n;x+=(x&-x)) s[x]+=y;} 11 LL search(LL x){LL an=0;for (;x>0;x-=(x&-x)) an+=s[x];return an;} 12 void PushDown(LL rt){ 13 if (la[rt]){ 14 t[rt<<1]+=la[rt]; 15 t[rt<<1|1]+=la[rt]; 16 la[rt<<1]+=la[rt]; 17 la[rt<<1|1]+=la[rt]; 18 la[rt]=0; 19 } 20 } 21 void PushUp(LL rt){ 22 t[rt]=max(t[rt<<1],t[rt<<1|1]); 23 } 24 void build(LL rt,LL l,LL r){ 25 la[rt]=0; 26 if (l==r){ 27 t[rt]=a[l]-search(l); 28 return; 29 } 30 LL m=(l+r)>>1; 31 build(lson); 32 build(rson); 33 PushUp(rt); 34 } 35 void upd(LL rt,LL l,LL r,LL x,LL y,LL z){ 36 if (x<=l && r<=y){ 37 la[rt]+=z; 38 t[rt]+=z; 39 return; 40 } 41 LL m=(l+r)>>1; 42 PushDown(rt); 43 if (x<=m) 44 upd(lson,x,y,z); 45 if (y>m) 46 upd(rson,x,y,z); 47 PushUp(rt); 48 } 49 LL srch(LL rt,LL l,LL r,LL x,LL y){ 50 if (x<=l && r<=y) return t[rt]; 51 LL m=(l+r)>>1,an=-10000000000000000ll; 52 PushDown(rt); 53 if (x<=m) 54 an=max(an,srch(lson,x,y)); 55 if (y>m) 56 an=max(an,srch(rson,x,y)); 57 return an; 58 } 59 int main(){ 60 // freopen ("e.in","r",stdin); 61 // freopen ("e.out","w",stdout); 62 LL i,j,x,y,z; 63 while (scanf("%lld%lld",&n,&cas)!=EOF){ 64 for (i=1;i<=n;i++){ 65 scanf("%lld",a+i); 66 s[i]=0; 67 } 68 for (i=1;i<=n;i++){ 69 scanf("%lld",b+i); 70 update(i,b[i]); 71 } 72 build(1,1,n); 73 while (cas--){ 74 scanf("%lld",&x); 75 if (x==1){ 76 scanf("%lld%lld",&y,&z); 77 upd(1,1,n,y,y,z-a[y]); 78 a[y]=z; 79 } 80 if (x==2){ 81 scanf("%lld%lld",&y,&z); 82 update(y,z-b[y]); 83 upd(1,1,n,y,n,b[y]-z); 84 b[y]=z; 85 } 86 if (x==3){ 87 scanf("%lld",&y); 88 printf("%lld\n",search(y)+max(0ll,srch(1,1,n,1,y))); 89 } 90 } 91 } 92 return 0; 93 } 94
未来是什么样,未来会发生什么,谁也不知道。
但是我知道,
起码从今天开始努力,
肯定比从明天开始努力,
要快一天实现梦想。
千里之行,始于足下! ——《那年那兔那些事儿》