您的位置:首页 > 其它

JZOJ4846【NOIP2016提高A组集训第5场11.2】行走

2016-11-02 20:28 399 查看

Description



Data Constraint

对于70%的数据保证 n <= 1000

对于100%的数据保证 n,q <= 10^5,c_i,v_i <= 10^{18}

保证每次修改后的边权小于等于原来的边权且不会小于1

Solution

这是一道树链剖分的模板题。只要将所有书取个对数,计算一下即可。

代码

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const ll maxn=200005;
int first[maxn],last[maxn],next[maxn],deep[maxn],a[maxn][2];
ll n,i,t,j,k,l,x,y,m,z,num,ans1,x2,y2,z2,value1[maxn],g[maxn*4],ans,d[maxn];
int dfn[maxn],top[maxn],son[maxn],size[maxn],b[maxn],fa[maxn];
double xx,value[maxn],f[maxn*4],c[maxn];
void lian(ll x,ll y,double z,ll z1){
last[++num]=y;next[num]=first[x];first[x]=num;value[num]=z;value1[num]=z1;
}
void dg(int x,int y){
ll t;fa[x]=y;size[x]++;deep[x]=deep[y]+1;
for (t=first[x];t;t=next[t]){
if (last[t]==y) continue;
c[last[t]]=value[t];
d[last[t]]=value1[t];
dg(last[t],x);
size[x]+=size[last[t]];
if (!son[x] || size[son[x]]<size[last[t]])son[x]=last[t];
}
}
void dg1(int x){
int t;dfn[x]=++num;b[num]=x;
if (son[x]) top[son[x]]=top[x],dg1(son[x]);
for (t=first[x];t;t=next[t]){
if (last[t]==fa[x] || last[t]==son[x]) continue;
top[last[t]]=last[t];
dg1(last[t]);
}
}
void insert(int l,int r,int v){
int mid=(l+r)/2;
if (l==r){
f[v]=c[b[l]];
g[v]=d[b[l]];
return;
}
insert(l,mid,v*2);
insert(mid+1,r,v*2+1);
f[v]=f[v*2]+f[v*2+1];
g[v]=g[v*2]*g[v*2+1];
}
void change(int l,int r,int v,int x){
int mid=(l+r)/2;
if (l==r){
f[v]=xx;
g[v]=z;
return;
}
if (mid>=x) change(l,mid,v*2,x);
else change(mid+1,r,v*2+1,x);
f[v]=f[v*2]+f[v*2+1];
g[v]=g[v*2]*g[v*2+1];
}
void find(int l,int r,int v,int x,int y){
int mid=(l+r)/2;
if (l>=x && r<=y){
z/=g[v];
xx-=f[v];
return;
}
if (l<=y && mid>=x) find(l,mid,v*2,x,y);
if (mid<y && r>=x) find(mid+1,r,v*2+1,x,y);
}
int main(){
freopen("walk.in","r",stdin);freopen("walk.out","w",stdout);
scanf("%lld%lld",&n,&m);
for (i=1;i<n;i++){
scanf("%lld%lld%lld",&x,&y,&z);
a[i][0]=x;a[i][1]=y;
xx=log(z)/log(2);
lian(x,y,xx,z),lian(y,x,xx,z);
}
dg(1,0);num=0;top[1]=1;
for (i=1;i<n;i++)
if (deep[a[i][0]]<deep[a[i][1]])swap(a[i][0],a[i][1]);
d[1]=1;
dg1(1);
insert(1,n,1);
if (n*m>10000000){
for (i=1;i<=m;i++){
scanf("%lld",&z);
if (z==1){
scanf("%lld%lld%lld",&x,&y,&z);
x2=x;y2=y;z2=z;
xx=log(z)/log(2);
while (top[x]!=top[y]){
if (deep[top[x]]>deep[top[y]]){
find(1,n,1,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}else{
find(1,n,1,dfn[top[y]],dfn[y]);
y=fa[top[y]];
}
}
if (dfn[x]>dfn[y]) swap(x,y);
if (dfn[x]<dfn[y]) find(1,n,1,dfn[x]+1,dfn[y]);
if (xx<0) ans=0;
else ans=z;
printf("%lld\n",ans);
}else{
scanf("%lld%lld",&x,&z);
xx=log(z)/log(2);
x=dfn[a[x][0]];
change(1,n,1,x);
}
}
}else{
for (i=1;i<=m;i++){
scanf("%lld",&z);
if (z==1){
scanf("%lld%lld%lld",&x,&y,&z);
while (x!=y){
if (deep[x]>deep[y]) z/=d[x],x=fa[x];
else z/=d[y],y=fa[y];
}
printf("%lld\n",z);
}else{
scanf("%lld%lld",&x,&z);
d[a[x][0]]=z;
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: