可惜没如果=_=
时光的河入海流

题目链接在本地

这道题如果按照题目意思去算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  

 

posted on 2022-07-09 16:16  珍珠鸟  阅读(19)  评论(0编辑  收藏  举报