您的位置:首页 > 其它

HDU 5044-tree-树链剖分+树状数组

2016-08-18 19:22 453 查看
裸的树链剖分,似乎数据有点大。用线段树维护会T,加个读入挂,树状数组能怼过去。。。

似乎连树状数组都没必要了。直接用数组也可做...

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
////////////
#define BUF_SIZE 100000

bool IOerror=0;
inline bool blank(char ch)
{
return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';
}

inline char nc()
{
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if (p1==pend)
{
p1=buf;
pend=buf+fread(buf,1,BUF_SIZE,stdin);
if (pend==p1)
{
IOerror=1;
return -1;
}
//{printf("IO error!\n");system("pause");for (;;);exit(0);}
}
return *p1++;
}
inline void read(int &x)
{
bool sign=0;
char ch=nc();
x=0;
for (; blank(ch); ch=nc());
if (IOerror)return;
if (ch=='-')sign=1,ch=nc();
for (; ch>='0'&&ch<='9'; ch=nc())x=x*10+ch-'0';
if (sign)x=-x;
}
inline void read(char *s)
{
char ch=nc();
for (; blank(ch); ch=nc());
if (IOerror)return;
for (; !blank(ch)&&!IOerror; ch=nc())*s++=ch;
*s=0;
}
///////////
typedef long long ll;
const int MAXN = 100000+50;
int n,m;
ll ans [MAXN];
int edge_id[MAXN];
struct Edge
{
int to,next;
} edge[MAXN*2];
int head[MAXN],tot;
int top[MAXN];//top[v]表示v所在的重链的顶端节点
int fa[MAXN]; //父亲节点
int deep[MAXN];//深度
int num[MAXN];//num[v]表示以v为根的子树的节点数
int p[MAXN];//p[v]表示v与其父亲节点的连边在线段树中的位置
int fp[MAXN];//和p数组相反
int son[MAXN];//重儿子
int pos;
int out[MAXN];//dfs序
void init()
{
tot = 0;
memset(head,-1,sizeof(head));
pos = 0;
memset(son,-1,sizeof(son));
}
void addedge(int u,int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void dfs1(int u,int pre,int d) //第一遍dfs求出fa,deep,num,son
{
deep[u] = d;
fa[u] = pre;
num[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v != pre)
{
dfs1(v,u,d+1);
num[u] += num[v];
if(son[u] == -1 || num[v] > num[son[u]])
son[u] = v;
}
}
}
void getpos(int u,int sp) //第二遍dfs求出top和p
{
top[u] = sp;
p[u] = ++pos;
fp[p[u]] = u;
if(son[u]!=-1)
getpos(son[u],sp);
for(int i = head[u] ; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v != son[u] && v != fa[u])
getpos(v,v);
}
out[u]=pos;
}
struct TREE
{
ll tree[MAXN+5];
void init()
{
memset(tree,0,sizeof tree);
}
int lowbit(int x)
{
return x&-x;
}
void add(int x,int value)
{
for (int i=x; i<=n; i=i+lowbit(i))
{
tree[i]+=value;
}
}
ll get(int x)
{
ll sum=0;
for (int i=x; i; i-=lowbit(i))
{
sum+=tree[i];
}
return sum;
}

void update_point(int u,int v,int z)//查询u->v链的sum
{
int f1=top[u],f2=top[v];
while(f1!=f2)
{
if (deep[f1]<deep[f2])
{
swap(f1,f2);
swap(u,v);
}
//update(1,1,pos,p[f1],p[u],z);
add(p[f1],z);
add(p[u]+1,-z);
u=fa[f1],f1=top[u];
}
if (deep[u]>deep[v] ) swap(u,v);
// update(1,1,pos,p[u],p[v],z); //若val(u)是u到fu的边权,则用son[u]
add(p[u],z);
add(p[v]+1,-z);
}
void update_edge(int u,int v,int z)//查询u->v链的sum
{
int f1=top[u],f2=top[v];
ll tmp=0;
while(f1!=f2)
{
if (deep[f1]<deep[f2])
{
swap(f1,f2);
swap(u,v);
}
// update(1,1,pos,p[f1],p[u],z);
add(p[f1],z);
add(p[u]+1,-z);
u=fa[f1],f1=top[u];
}
if (u==v) return ;
if (deep[u]>deep[v] ) swap(u,v);
if (p[son[u]]>p[v]) return ;
// update(1,1,pos,p[son[u]],p[v],z); //若val(u)是u到fu的边权,则用son[u]
add(p[son[u]],z);
add(p[v]+1,-z);
}
void get_ans( )
{
for (int i=1;i<=n;i++)
ans[fp[i]]=get(i);
}
void get_ans_edge()
{
for (int i=1;i<=n;i++)
{
int x=fp[i];
int id=edge_id[x];
ans[id]=get(i);
}
}
};
TREE tp;

struct node
{
int x,y,z;
node () {}
node(int a,int b,int c)
{
x=a,y=b,z=c;
}
};
vector<node> a1;
vector<node> a2;
int uu[MAXN];
int vv[MAXN];
int main()
{
// freopen("in.txt","r",stdin);
int cnt=1;
int t;
//cin>>t;
read(t);
while(t--)
{

a1.clear();
a2.clear();
init();
// scanf("%d%d",&n,&m);
read(n);
read(m);
int u,v;
for (int i=1; i<n; i++)
{
// scanf("%d%d",&uu[i],&vv[i]);

read(uu[i]);
read(vv[i]);
u=uu[i],v=vv[i];
addedge(u,v);
addedge(v,u);
}

char stmp[15];
int x,y,z;
for (int i=1; i<=m; i++)
{
// scanf("%s%d%d%d",stmp,&x,&y,&z);
read(stmp);
read(x);
read(y);
read(z);
if (stmp[3]=='1')
a1.push_back(node(x,y,z));
else
a2.push_back(node(x,y,z));
}
printf("Case #%d:\n",cnt++);
dfs1(1,0,0);
getpos(1,1);
tp.init();
//tp.build(1,pos,1);
for (int i=1; i<n; i++)
{
int u=uu[i],v=vv[i];
if (u==fa[v])
edge_id[v]=i;
else edge_id[u]=i;

}

for (int i=0; i<a1.size(); i++)
{
node tt=a1[i];
int x=tt.x,y=tt.y,z=tt.z;
tp.update_point(x,y,z);
}
tp.get_ans();
for(int i=1; i<=n; i++)
{
if (i>1) printf(" ");
printf("%lld",ans[i]);
}
printf("\n");

tp.init();
for (int i=0; i<a2.size(); i++)
{
node tt=a2[i];
int x=tt.x,y=tt.y,z=tt.z;
tp.update_edge(x,y,z);
}

tp.get_ans_edge();
for(int i=1; i<n; i++)
{
if (i>1) printf(" ");
printf("%lld",ans[i]);
}
printf("\n");
}
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: