2017 暑假艾教集训 day8 (树链剖分+树上点分治)
来源:互联网 发布:沙宣男士洗发水 知乎 编辑:程序博客网 时间:2024/06/06 01:40
POJ 2763
树链剖分 边权化点权问题(只需要把边的权值给深度大的节点转换为点权值问题即可)
#include <iostream>#include <cstring>#include <cstdio>#include <cmath>#include <algorithm>using namespace std;const int maxn=100100;int n,m,s;struct node{ int to,next;}edge[maxn*3];int u[maxn],v[maxn],w[maxn],head[maxn],cnt=0;void add(int u,int v){ edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++;}int siz[maxn] , son[maxn] , fa[maxn] , deep[maxn] ;int tid[maxn] , top[maxn] ,tot=0;void dfs1(int u,int d,int pre){ siz[u]=1; fa[u]=pre; deep[u] = d; for(int i=head[u] ; i!=-1 ;i=edge[i].next) { int v=edge[i].to; if(v!=pre) { dfs1(v,d+1,u); siz[u]+=siz[v]; if(son[u]==-1 || siz[v]>siz[son[u]]) { son[u]=v; } } }}void dfs2(int u,int tp){ top[u]=tp; tid[u]=++tot; if(son[u]==-1) return; dfs2(son[u],tp); for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v!=son[u] && v!=fa[u]) { dfs2(v,v); } }}#define lson rt<<1,begin,mid#define rson rt<<1|1,mid+1,endint tree[maxn<<2];void pushup(int rt){ tree[rt] = tree[rt<<1] + tree[rt<<1|1];}void updata(int rt,int begin,int end ,int pos,int val){ if(begin==end) { tree[rt] = val; return; } int mid=(begin + end)>>1; if(mid>=pos) updata(lson,pos,val); else updata(rson,pos,val); pushup(rt);}int query(int rt,int begin,int end,int l,int r){ if(begin >=l && r>=end) { return tree[rt]; } int mid=(begin+end)>>1 ; int ans=0; if(mid >= l) ans+=query(lson,l,r); if(r > mid) ans+=query(rson ,l,r); return ans;}int getsum(int u,int v){ int ans=0; while(top[u] != top[v]) { if(deep[top[u]] < deep[top[v]]) swap(u,v); ans += query(1,1,n,tid[top[u]],tid[u]); u = fa[top[u]]; } if(u==v) return ans; if(deep[u] > deep[v]) swap(u,v); return ans+query(1,1,n,tid[son[u]],tid[v]) ; // 为啥!!!}int main(){ while(scanf("%d%d%d",&n,&m,&s)!=EOF) { memset(head,-1,sizeof(head)); cnt=0; memset(son,-1,sizeof(son)); tot=0; for(int i=0;i<n-1;++i) { scanf("%d%d%d",&u[i],&v[i],&w[i]); add(u[i],v[i]); add(v[i],u[i]); } dfs1(1,0,0); dfs2(1,1); memset(tree,0,sizeof(tree)); for(int i=0;i<n-1;++i) { if(deep[u[i]]<deep[v[i]]) swap(u[i],v[i]); updata(1,1,n,tid[u[i]],w[i]); } while(m--) { int op; scanf("%d",&op); if(op==0) { int x; scanf("%d",&x); printf("%d\n",getsum(s,x)); s=x; } else if(op==1) { int i,val; scanf("%d%d",&i,&val); updata(1,1,n,tid[u[i-1]],val); } } } return 0;}
POJ 1741
树上点分治第一题,还是没太懂,先存下来以后慢慢研究
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int maxn=11111;struct node{ int to,next,w;}edge[maxn*5];int head[maxn] , cnt=0;void add(int u,int v,int w){ edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u] = cnt++;}int siz[maxn] , mx[maxn] ,deep[maxn] ,vis[maxn];int dis[maxn] , num , mi, root ,ans , n, k;void dfssize(int u,int pre){ siz[u]=1; mx[u]=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v!=pre && !vis[v]) { dfssize(v,u); siz[u] +=siz[v]; if(siz[v]>mx[u]) mx[u]=siz[v]; } }}void dfsroot(int r,int u,int fa){ if(siz[r] - siz[u] > mx[u]) mx[u] = siz[r] -siz[u]; if(mx[u] < mi) mi=mx[u] , root=u; for(int i=head[u];i!=-1; i=edge[i].next) { int v=edge[i].to; if(v!=fa && !vis[v]) dfsroot(r,v,u); }}void dfsdis(int u,int step,int pre){ dis[num++]=step; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v!=pre &&!vis[v]) dfsdis(v,step+edge[i].w,u); }}int work(int u,int step){ int ret=0; num=0; dfsdis(u,step,0); sort(dis,dis+num); int i=0 , j=num-1; while(i<j) { while(dis[i] + dis[j] > k && i < j ) j--; ret += (j-i); i++; } return ret;}int dfs(int u){ mi=n; dfssize(u,0); dfsroot(u,u,0); ans += work(root,0); vis[root] = 1; for(int i=head[root];i!=-1;i=edge[i].next) { int v=edge[i].to; if(!vis[v]) { ans-=work(v,edge[i].w); dfs(v); } } return ans;}int main(){ while(scanf("%d%d",&n,&k)!=EOF) { if(!n && !k)break; memset(vis,0,sizeof(vis)); memset(head,-1,sizeof(head)); cnt=0; ans=0; int u,v,w; for(int i=0;i<n-1;++i) { scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } dfs(1); printf("%d\n",ans); } return 0;}
阅读全文
0 0
- 2017 暑假艾教集训 day8 (树链剖分+树上点分治)
- 2017 暑假艾教集训 day8 (补一道思维题,
- 2017暑假七林集训day8
- 2017 暑假艾教集训 day7 (树链剖分模板)
- 2017 暑假艾教集训 day9(整体二分 + cdq分治 cdq真是我女神!!!)
- 2017 暑假艾教集训 day1
- 2017 暑假艾教集训 day2
- 2017 暑假艾教集训 day3
- 2017 暑假艾教集训 day4
- 2017 暑假艾教集训 day5
- 2017 暑假艾教集训 day6
- 【POJ 1741】Tree (树上点分治)
- gdfzoj #510 树上路径(点分治)
- poj1741 树上点分治
- POJ1741Tree(树上点分治)
- 树上点分治入门
- 树上点分治学习记录
- POJ_P1741 Tree(树上点分治)
- MySQL基础教程之存储过程
- 2017.08.08
- 错误提示:warning: push.default is unset
- redis连接不了客户端的问题
- Dockers Job for docker.service failed because the control process exited with error code
- 2017 暑假艾教集训 day8 (树链剖分+树上点分治)
- 线程池原理
- JS 原型
- 前端笔记——node.js
- 无限引流大助手3.0开源版
- Oracle中left join,right join,inner join分析
- 多线程之多个窗口卖票02
- 爬格子呀4-1
- SAPUI5教程——在XML View中使用$运算符