您的位置:首页 > 其它

2017 暑假艾教集训 day8 (树链剖分+树上点分治)

2017-08-09 02:08 453 查看
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,end
int 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: