CodeForces
来源:互联网 发布:淘宝号信誉等级查询 编辑:程序博客网 时间:2024/06/06 05:09
题意:
有n个结点,标为1~n,,形成了一棵以1为根节点的树,有m个操作,,
操作有两种:
1。某个节点的值加上v,该节点的隔代都加上v,,该节点的子代以及子代的隔代都减去v。
2。查询某个节点的值。
n,m<=2e5
如果修改节点值直接暴力dfs的话,时间复杂度为O(n*m),显然超时。
可以看出,修改操作,其实是修改两个区间的值,,,那么可以想到线段树区间修改,lazy一下时间就可以优化到m*logn;
关键是如何保证修改区间时,区间是连续。如果直接以节点的标号为区间下标,显然是不行的。
这时可以为这棵树维护一个dfs序(具体见代码),保证修改某个位置时,修改的区间是连续的。
代码:
#include <bits/stdc++.h>using namespace std;const int maxn = 200000+7;struct node{ int x1,x2,y1,y2;}e[maxn];int n,m,a[maxn],bef[maxn],lazy[maxn*4],index = 1;vector<int> arr[maxn];void dfs1(int u,int dep,int fa){ if(dep==1) bef[u] = index++; int len = arr[u].size(); for(int i = 0;i<len;i++) { int v = arr[u][i]; if(v!=fa) { dfs1(v,1-dep,u); } }}void dfs2(int u,int fa){ int len = arr[u].size(); for(int i = 0;i<len;i++) if(arr[u][i]!=fa) dfs2(arr[u][i],u); int r1 = bef[u],l2 = maxn,r2 = 0; for(int i = 0;i<len;i++) { int v = arr[u][i]; if(v!=fa) { r1 = max(e[v].y2,r1); l2 = min(e[v].x1,l2); r2 = max(e[v].y1,r2); } } e[u].x1 = bef[u],e[u].y1 = r1; e[u].x2 = l2,e[u].y2 = r2;}void pushdown(int rt){ lazy[rt<<1] += lazy[rt]; lazy[(rt<<1)+1] += lazy[rt]; lazy[rt] = 0;}void build(int rt,int l,int r){ if(l==r) { lazy[rt] = 0; return ; } int mid = (l+r)>>1; build(rt<<1,l,mid); build((rt<<1)+1,mid+1,r); lazy[rt] = 0;}void update(int rt,int l,int r,int ql,int qr,int v){ if(ql<=l&&r<=qr) { lazy[rt] += v; return ; } pushdown(rt); int mid = (l+r)>>1; if(ql<=mid) update(rt<<1,l,mid,ql,qr,v); if(qr>mid) update((rt<<1)+1,mid+1,r,ql,qr,v);}int query(int rt,int l,int r,int q){ if(l==r) { return lazy[rt]; } pushdown(rt); int mid = (l+r)>>1; if(q<=mid) return query(rt<<1,l,mid,q); return query((rt<<1)+1,mid+1,r,q);}int main(){ scanf("%d%d",&n,&m); for(int i = 1;i<=n;i++) scanf("%d",a+i); for(int i = 1;i<=n-1;i++) { int u,v; scanf("%d%d",&u,&v); arr[u].push_back(v); arr[v].push_back(u); } dfs1(1,1,0); int len = arr[1].size(); for(int i = 0;i<len;i++) dfs1(arr[1][i],1,1); dfs2(1,0); //for(int i = 1;i<=n;i++) // cout<<e[i].x2<<" "<<e[i].y2<<endl; build(1,1,n); while(m--) { int ty; scanf("%d",&ty); if(ty==1) { int q,v; scanf("%d%d",&q,&v); //cout<<e[q].x1<<" "<<e[q].y1<<endl; //cout<<e[q].x2<<" "<<e[q].y2<<endl; update(1,1,n,e[q].x1,e[q].y1,v); if(e[q].y2!=0) update(1,1,n,e[q].x2,e[q].y2,-v); } else { int q; scanf("%d",&q); printf("%d\n",query(1,1,n,bef[q])+a[q]); } } return 0;}
区间修改+单点查询,用线段树写即耗内存,代码又长。
树状数组有一种操作可以高效的实现 区间修改+单点查询///。修改区间[L,R]相当于add(L,V);add(R+1,-V),,,但此时getSum(x)的值变为了下标为x的值。
代码:
#include <bits/stdc++.h>using namespace std;const int maxn = 200000+7;struct node{ int x1,x2,y1,y2;}e[maxn];int n,m,a[maxn],bef[maxn],tree[maxn],index = 1;vector<int> arr[maxn];void dfs1(int u,int dep,int fa){ if(dep==1) bef[u] = index++; int len = arr[u].size(); for(int i = 0;i<len;i++) { int v = arr[u][i]; if(v!=fa) { dfs1(v,1-dep,u); } }}void dfs2(int u,int fa){ int len = arr[u].size(); for(int i = 0;i<len;i++) if(arr[u][i]!=fa) dfs2(arr[u][i],u); int r1 = bef[u],l2 = maxn,r2 = 0; for(int i = 0;i<len;i++) { int v = arr[u][i]; if(v!=fa) { r1 = max(e[v].y2,r1); l2 = min(e[v].x1,l2); r2 = max(e[v].y1,r2); } } e[u].x1 = bef[u],e[u].y1 = r1; e[u].x2 = l2,e[u].y2 = r2;}int getSum(int x){ int ans = 0; while(x>0) { ans += tree[x]; x -= x&(-x); } return ans;}void add(int k,int v){ while(k<=n) { tree[k] += v; k += k&(-k); }}int main(){ scanf("%d%d",&n,&m); memset(tree,0,sizeof(tree)); for(int i = 1;i<=n;i++) scanf("%d",a+i); for(int i = 1;i<=n-1;i++) { int u,v; scanf("%d%d",&u,&v); arr[u].push_back(v); arr[v].push_back(u); } dfs1(1,1,0); int len = arr[1].size(); for(int i = 0;i<len;i++) dfs1(arr[1][i],1,1); dfs2(1,0); //for(int i = 1;i<=n;i++) // cout<<e[i].x2<<" "<<e[i].y2<<endl; while(m--) { int ty; scanf("%d",&ty); if(ty==1) { int q,v; scanf("%d%d",&q,&v); //cout<<e[q].x1<<" "<<e[q].y1<<endl; //cout<<e[q].x2<<" "<<e[q].y2<<endl; add(e[q].x1,v); add(e[q].y1+1,-v); if(e[q].y2!=0) add(e[q].x2,-v),add(e[q].y2+1,v); } else { int q; scanf("%d",&q); printf("%d\n",getSum(bef[q])+a[q]); } } return 0;}
阅读全文
1 0
- codeforces~~~
- Codeforces
- codeforces
- Codeforces
- codeforces
- codeforces
- Codeforces
- Codeforces
- CodeForces
- CodeForces
- CodeForces
- CodeForces
- CodeForces
- Codeforces
- Codeforces
- Codeforces
- Codeforces
- Codeforces
- axios 使用文档
- Jenkins启动slave的方法
- Effective STL 24 Choose carefully between map::operator[] and map::insert
- 设计模式的应用场景(11)--组合模式
- 记录一次自定义参数绑定错误问题的解决过程
- CodeForces
- EasyNVR H5无插件直播方案前端构建之:引用videojs无法自动播放
- 【算法】字符串循环左移K位
- 【Java】内存模型 volatile
- android retrofit2使用全解
- 二叉树的各种操作(面试必备)
- Cookie没有HttpOnly标志
- serialVersionUID的作用
- android如何编差分包升级