rebuild hnoi省选集训 分类: templates 2015-03-28 15:30 42人阅读 评论(0) 收藏
树链剖分+线段树
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<iostream>
#include<algorithm>
const int MAXN = 100005;const double eps = 1e-8;
int n, q;
struct edge{int v,next;}mp[MAXN<<1];int ml = 0;
int dfo[MAXN<<1] = {0}, dl = 0 ,head[MAXN] = {0};
int dep[MAXN] = {0},size[MAXN] = {0},fa[MAXN] = {0},son[MAXN] = {0};
int fc[MAXN] = {0} , fl = 0 , top[MAXN] = {0} , end[MAXN] = {0};
double value;
struct treenode{double sum,max,min;double lazy;int tag;}tree[MAXN<<2] = {{0,0,0,0,0}},emp = {0,0,0,0,0};
// tag = 1 plus! tag = 2 transform!
void newedge(int u0,int v0)
{
++ml,mp[ml].v=v0;
mp[ml].next=head[u0];
head[u0] = ml;
}
void dfs1(int a)
{
size[a] = 1;
for(int i = head[a]; i ; i = mp[i].next)
{
int p = mp[i].v;
if(p == fa[a])continue;
fa[p] = a; dep[p] = dep[a]+1;
dfs1(p); size[a]+=size[p];
if(size[p]>size[son[a]])son[a] = p;
}
}
void dfs2(int a)
{
dfo[++dl] = a;
fc[a] = ++fl;
top[a] = a;
if(son[fa[a]]==a)
top[a] = top[fa[a]];
if(son[a]){dfs2(son[a]);}
for(int i = head[a]; i ; i = mp[i].next)
{
int p = mp[i].v;
if(p == fa[a] || p == son[a])continue;
dfs2(p);
}
end[a] = fl;
dfo[++dl] = a;
}
#define L(x) (x<<1)
#define R(x) ((x<<1)|1)
void update(int x)
{
tree[x].sum = tree[L(x)].sum+tree[R(x)].sum;
tree[x].max = std::max(tree[L(x)].max,tree[R(x)].max);
tree[x].min = std::min(tree[L(x)].min,tree[R(x)].min);
}
void gather(treenode &ans,const treenode &a,const treenode &b)
{
ans.max = std::max(a.max , b.max);
ans.min = std::min(a.min , b.min);
ans.sum = a.sum + b.sum;
}
void pushdown(int x,int ll,int rr)
{
int mid = (ll+rr)>>1;
if(tree[x].tag==1)
{
tree[L(x)].max += tree[x].lazy,tree[R(x)].max += tree[x].lazy;
tree[L(x)].min += tree[x].lazy,tree[R(x)].min += tree[x].lazy;
tree[L(x)].sum += tree[x].lazy*(mid-ll+1);
tree[R(x)].sum += tree[x].lazy*(rr-mid);
tree[L(x)].lazy+=tree[x].lazy;
tree[R(x)].lazy+=tree[x].lazy;
if(!tree[L(x)].tag)tree[L(x)].tag = 1;
if(!tree[R(x)].tag)tree[R(x)].tag = 1;
}
else if(tree[x].tag==2)
{
tree[L(x)].max = tree[L(x)].min = tree[x].lazy;
tree[R(x)].max = tree[R(x)].min = tree[x].lazy;
tree[L(x)].sum = tree[x].lazy*(mid-ll+1);
tree[R(x)].sum = tree[x].lazy*(rr-mid);
tree[L(x)].lazy=tree[R(x)].lazy=tree[x].lazy;
tree[L(x)].tag = tree[R(x)].tag = 2;
}
tree[x].lazy = tree[x].tag = 0;
}
void add(int ll,int rr,int l,int r,int si)
{
if(ll==l && rr==r)
{
if(!tree[si].tag)
tree[si].tag=1;
tree[si].lazy+=value;
tree[si].min+=value;
tree[si].max+=value;
tree[si].sum+=value*(r-l+1);
}
else
{
pushdown(si,ll,rr);
int mid = (ll+rr)>>1;
if(r<=mid)
add(ll,mid,l,r,L(si));
else if(l>mid)
add(mid+1,rr,l,r,R(si));
else
{
add(ll,mid,l,mid,L(si));
add(mid+1,rr,mid+1,r,R(si));
}
update(si);
}
}
void change(int ll,int rr,int l,int r,int si)
{
if(ll==l && rr==r)
{
tree[si].tag=2;
tree[si].lazy=value;
tree[si].min=value;
tree[si].max=value;
tree[si].sum=value*(r-l+1);
}
else
{
pushdown(si,ll,rr);
int mid = (ll+rr)>>1;
if(r<=mid)
change(ll,mid,l,r,L(si));
else if(l>mid)
change(mid+1,rr,l,r,R(si));
else
{
change(ll,mid,l,mid,L(si));
change(mid+1,rr,mid+1,r,R(si));
}
update(si);
}
}
double getsum(int ll,int rr,int l,int r,int si)
{
if (ll==l && rr==r)return tree[si].sum;
int mid=(ll+rr)>>1;
pushdown(si,ll,rr);
if (r<=mid)
return getsum(ll,mid,l,r,L(si));
else if (mid<l)
return getsum(mid+1,rr,l,r,R(si));
else
return getsum(ll,mid,l,mid,L(si))+getsum(mid+1,rr,mid+1,r,R(si));
}
void query(treenode &ret,int ll,int rr,int l,int r,int si)
{
if (ll==l && rr==r)
{ret = tree[si];return;}
int mid=(ll+rr)>>1;
pushdown(si,ll,rr);
if (r<=mid)
query(ret,ll,mid,l,r,L(si));
else if (mid<l)
query(ret,mid+1,rr,l,r,R(si));
else
{
treenode tl,tr;
query(tl,ll,mid,l,mid,L(si));
query(tr,mid+1,rr,mid+1,r,R(si));
gather(ret,tl,tr);
}
}
#undef L
#undef R
void N(int a,int b)
{
scanf("%lf",&value);
while(top[a]!=top[b])
{
if(dep[top[a]]>dep[top[b]])
std::swap(a,b);
//dep[top[a]]<dep[top[b]] lift node b
add(1,n,fc[top[b]],fc[b],1);
b = fa[top[b]];
}
if(dep[a]>dep[b])std::swap(a,b);
//dep[a]<dep[b] node a ~ node b
add(1,n,fc[a],fc[b],1);
}
void F(int a,int b)
{
double sum = 0;int num = 0;
int a0 = a,b0 = b;
while(top[a]!=top[b])
{
if(dep[top[a]]>dep[top[b]])
std::swap(a,b);
//dep[top[a]]<dep[top[b]] lift node b
sum+=getsum(1,n,fc[top[b]],fc[b],1);
num+=fc[b]-fc[top[b]]+1;
b = fa[top[b]];
}
if(dep[a]>dep[b])std::swap(a,b);
//dep[a]<dep[b] node a ~ node b
sum+=getsum(1,n,fc[a],fc[b],1);
num+=fc[b]-fc[a]+1;
value = sum/num;
a = a0, b = b0;
while(top[a]!=top[b])
{
if(dep[top[a]]>dep[top[b]])
std::swap(a,b);
//dep[top[a]]<dep[top[b]] lift node b
change(1,n,fc[top[b]],fc[b],1);
b = fa[top[b]];
}
if(dep[a]>dep[b])std::swap(a,b);
//dep[a]<dep[b] node a ~ node b
change(1,n,fc[a],fc[b],1);
}
void C(int a,int b)
{
treenode ans = emp,tmp,caltmp;
ans.max = 0;
ans.min = 1e10;
ans.sum = 0;
while(top[a]!=top[b])
{
if(dep[top[a]]>dep[top[b]])
std::swap(a,b);
//dep[top[a]]<dep[top[b]] lift node b
query(tmp,1,n,fc[top[b]],fc[b],1);
caltmp = ans;gather(ans,caltmp,tmp);
b = fa[top[b]];
}
if(dep[a]>dep[b])std::swap(a,b);
//dep[a]<dep[b] node a ~ node b
query(tmp,1,n,fc[a],fc[b],1);
caltmp = ans;gather(ans,caltmp,tmp);
printf("%lf %lf %lf\n",ans.min,ans.max,ans.sum);
}
void NN(int a)
{
scanf("%lf",&value);
add(1,n,fc[a],end[a],1);
}
void FF(int a)
{
double sum = 0;int num = 0;
sum = getsum(1,n,fc[a],end[a],1);
num = end[a] - fc[a]+1;
value = sum/num;
change(1,n,fc[a],end[a],1);
}
void CC(int a)
{
treenode ans;
query(ans,1,n,fc[a],end[a],1);
printf("%lf %lf %lf\n",ans.min,ans.max,ans.sum);
}
int main()
{
int T;
freopen("rebd.in","r",stdin);
freopen("rebd.out","w",stdout);
scanf("%d",&T);
scanf("%d%d",&n,&q);
for(int i = 1; i < n ;i++)
{
int a,b;scanf("%d%d",&a,&b);
newedge(a,b);newedge(b,a);
}
dfs1(1); dfs2(1);
for(int i = 1 ; i <= q ; i++)
{
char ch[5]={'\0'};
scanf("%s",ch);
if(strlen(ch)==1)
{
int a,b;scanf("%d%d",&a,&b);
switch(ch[0])
{
case 'N':N(a,b);break;
case 'F':F(a,b);break;
case 'C':C(a,b);break;
}
}
else
{
int a;scanf("%d",&a);
switch(ch[0])
{
case 'N':NN(a);break;
case 'F':FF(a);break;
case 'C':CC(a);break;
}
}
}
fclose(stdin);
fclose(stdout);
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。