又是一个线段树问题,做了那么多的线段树,遇到这个题,还真是好难为我啊,看了好久都没看出来怎么做!
看了很久思维只局限在单点更新上,怎么想都是死胡同,直到,突然闪电击中了大脑,然后,然后,原来这个题是区间更新,(#‵′)靠。
具体的思路是:每个点和其后面的k个点的和算作一个点,然后,更新的时候,更新影响到的点,查询的时候,查询需查询区间的多有相应的点的最值即可!
这个题的关键是区间更新,一个点的变化,他会影响到k个处理好的点!
想出来思路就知道为什么这个题的k是固定的了!也只有k是固定的,才能想出用这种方法!
其实,题目中往往会隐藏很多可以思考的点,例如,这个题目中的固定的k,有时候,思考点是给的是不大的数据,当然,时间复杂度成为了基本的知识点!
最近我越来越觉得,真正的比赛,不仅看你学到多少,会了多少东西,最重要的是,看你赛场上能够想起多少东西。然后我就想起来了《暗时间》中说的。其实记忆这个东西,很奇怪,他只是建立了一些神经元的突起,真正让你回忆起来的是一些所谓的“线索”,当抓到这些线索,你就能拽出很多东西,使劲刷题切题的时候,注意多建立一些“线索”,到比赛的时候好有的拽!哈哈,简单来说,就是多想、多学、多总结,多做笔记。总之就是,你记住的,但是用得着的时候想不起来的东西,只能说你没记住!
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; #define N 200010 int dat[N],sum[N]; int n,m,k; ///线段树 区间更新 区间最值 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define fmid int m = (l+r)>>1 int ma[N*4],cnt[N*4]; void Push_up(int rt) { ma[rt] = max(ma[rt<<1],ma[rt<<1|1]); } void Push_down(int rt) { if(cnt[rt] != 0) { ma[rt<<1] += cnt[rt]; ma[rt<<1|1] += cnt[rt]; cnt[rt<<1] += cnt[rt]; cnt[rt<<1|1] += cnt[rt]; cnt[rt] = 0; } } void build(int l,int r,int rt) { cnt[rt] = 0; if(l == r) { ma[rt] = sum[l+k-1] - sum[l-1]; return ; } fmid; build(lson); build(rson); Push_up(rt); } void update(int L,int R,int val,int l,int r,int rt) { if(L <= l && r <= R) { cnt[rt] += val; ma[rt] += val; return ; } Push_down(rt); fmid; if(L <= m) update(L,R,val,lson); if(m < R) update(L,R,val,rson); Push_up(rt); } int query(int L,int R,int l,int r,int rt) { if(L <= l && r <= R) { return ma[rt]; } Push_down(rt); fmid; int re = -999999999; //cout << re << " "; if(L <= m) re = max(re,query(L,R,lson)); if(m < R) re = max(re,query(L,R,rson)); return re; } int main() { int t; cin >> t; while(t--) { scanf("%d%d%d",&n,&m,&k); for(int i = 1;i <= n;i++) scanf("%d",&dat[i]); sum[0] = 0; for(int i = 1;i <= n;i++) sum[i] = sum[i-1] + dat[i]; build(1,n-k+1,1); int p,x,y; while(m--) { scanf("%d%d%d",&p,&x,&y); if(p == 0) { update(max(1,x - k + 1),min(x,n-k+1),y - dat[x],1,n-k+1,1); dat[x] = y; }else if(p == 1) { update(max(1,x - k + 1),min(x,n-k+1),dat[y] - dat[x],1,n-k+1,1); update(max(1,y - k + 1),min(y,n-k+1),dat[x] - dat[y],1,n-k+1,1); int t = dat[x];dat[x] = dat[y];dat[y] = t; }else { int tt = query(x,y-k+1,1,n-k+1,1); printf("%d\n",tt); } } } return 0; }