您的位置:首页 > 其它

HDU 5044 (树链剖分+树状数组+点/边改查)

2014-10-08 17:46 232 查看
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5044

题目大意:修改链上点,修改链上的边。查询所有点,查询所有边。

解题思路

2014上海网赛的变态树链剖分模板题。将以往树链剖分的点&边修改和查询合在一起之后,难度上去不少。

第一个卡人点是读入优化。

第二个卡人点是树状数组。由于要查询所有点,如果使用线段树,每次都要扫到底层才能取出点值,必T无疑。

然后使用树状数组之后,树链剖分的点/边修改写法有些变动。

点查询变化不大。

边查询只要查询一下dep(u,v)大的那一端。

具体变化请仔细看代码。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include "cstdio"
#include "cstring"
#include "iostream"
using namespace std;
#define maxn 100005
template <class T>
inline bool read(T &ret)
{
char c;
int sgn;
if(c=getchar(),c==EOF) return 0; //EOF
while(c!='-'&&(c<'0'||c>'9')) c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
ret*=sgn;
return 1;
}
int s[maxn],dep[maxn],w[maxn],fa[maxn],top[maxn],son[maxn],tol,cnt,n,head[maxn];
struct Edge
{
int u,v,c;
}edge[maxn];
struct EDGE
{
int next,to;
}e[2*maxn];
void addedge(int u,int v)
{
e[tol].to=v;
e[tol].next=head[u];
head[u]=tol++;
}
void dfs1(int u,int pre,int d)
{
s[u]=1;fa[u]=pre;dep[u]=d;son[u]=-1;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(v==pre) continue;
dfs1(v,u,d+1);
s[u]+=s[v];
if(son[u]!=-1||s[v]>s[son[u]]) son[u]=v;
}
}
void dfs2(int u,int tp)
{
w[u]=++cnt;top[u]=tp;
if(son[u]!=-1) dfs2(son[u],tp);
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(v!=son[u]&&v!=fa[u]) dfs2(v,v);
}
}
//Binary-Indexed-Tree type:0-point,1-edge
int psum[maxn],esum[maxn];
inline int lowbit(int x) {return x&(-x);}
int sum(int x,int type)
{
int ret=0;
while(x>0)
{
if(!type) ret+=psum[x];
else ret+=esum[x];
x-=lowbit(x);
}
return ret;
}
void add(int x,int d,int type)
{
while(x<=n)
{
if(!type) psum[x]+=d;
else esum[x]+=d;
x+=lowbit(x);
}
}
void p_Change(int x,int y,int v)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
add(w[top[x]],v,0);
add(w[x]+1,-v,0);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
add(w[x],v,0);
add(w[y]+1,-v,0);
}
void e_Change(int x,int y,int v)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
add(w[top[x]],v,1);
add(w[x]+1,-v,1);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
if(x!=y) //这个判断非常重要,没有的话T死你
{
add(w[son[x]],v,1);
add(w[y]+1,-v,1);
}
}
int main()
{
//freopen("in.txt","r",stdin);
int T,u,v,c,m,no=0;
char cmd[10];
read(T);
while(T--)
{
memset(head,-1,sizeof(head));
memset(esum,0,sizeof(esum));
memset(psum,0,sizeof(psum));
tol=cnt=0;
read(n);read(m);
for(int i=1;i<n;i++)
{
read(edge[i].u);read(edge[i].v);
addedge(edge[i].u,edge[i].v);
addedge(edge[i].v,edge[i].u);
}
dfs1(1,1,1);
dfs2(1,1);
for(int i=1;i<n;i++)
if(dep[edge[i].u]<dep[edge[i].v]) swap(edge[i].u,edge[i].v);
while(m--)
{
scanf("%s",cmd);
read(u);read(v);read(c);
if(cmd[3]=='1') p_Change(u,v,c);
if(cmd[3]=='2') e_Change(u,v,c);
}
printf("Case #%d:\n",++no);
for(int i=1;i<=n;i++) {if(i>=2) printf(" ");printf("%d",sum(w[i],0));}
printf("\n");
for(int i=1;i<n;i++) {if(i>=2) printf(" ");printf("%d",sum(w[edge[i].u],1));}
printf("\n");
}
}


118245252014-10-08 17:34:00Accepted50443718MS11576K3384 BC++Physcal
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: