【NOIP模拟】行走 题面 分析 代码
“我有个愿望,我希望走到你身边。”
这是个奇异的世界,世界上的n-1条路联结起来形成一棵树,每条路有一个对应的权值ci。
现在我会给出q组询问或操作。
每次询问我会从一个x点走到y点,初始在x点我会有一个数字v,然后每走过一条权值为c的边,我的v就会变成v/c(向下取整),问最后到y时v变成了什么。
每次修改我会修改一条边的权值,保证修改后的权值小于等于原来的权值且不会小于1。
每组询问或操作的格式如下:
询问:1 x y v表示从x走到y,一开始的数字为v。
操作:2 p c表示将第p条边的边权修改为c
对于70%的数据保证n<=1000
对于100%的数据保证n,q<=100000,c_i,v_i <= 10^{18}
保证每次修改后的边权小于等于原来的边权且不会小于1
分析
分析啥啊,我打的暴力啊?为啥过了??懵逼中
代码
#include<bits/stdc++.h> using namespace std; #define N 100100 #define ll long long int n,q,op,ans,cnt,tot; ll val[N]; int dep[N],first[N],f[N][20],fc[N]; struct email { int u,v; ll w; int nxt; }e[N*4]; inline void add(int u,int v,ll w) { e[++cnt].nxt=first[u];first[u]=cnt; e[cnt].u=u;e[cnt].v=v;e[cnt].w=w; } inline void read(int &x) { x=0;int fh=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} x*=fh; } inline void readl(ll &x) { x=0;int fh=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} x*=fh; } void pre(int u,int fa) { for(int i=1;(1<<i)<=dep[u];i++) f[u][i]=f[f[u][i-1]][i-1]; for(int i=first[u];i;i=e[i].nxt) { int v=e[i].v; if(v==fa)continue; dep[v]=dep[u]+1; f[v][0]=u; pre(v,u); } } inline int lca(int x,int y) { int len=1; if(dep[x]<dep[y]) swap(x,y); int t=dep[x]-dep[y]; for(int i=0;(1<<i)<=t;i++) if(t&(1<<i)) x=f[x][i]; if(x==y)return x; for(int i=19;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0]; } void dfs(int u,int fa,int tar,int k) { for(int i=first[u];i;i=e[i].nxt) { int v=e[i].v; ll w=e[i].w; if(v==fa||dep[v]>dep[u])continue; val[k]/=w; if(v==tar)return; dfs(v,u,tar,k); } } void solve1() { for(int i=1;i<=q;i++) { read(op); if(op==1) { int x,y,pref;ll v; read(x);read(y);readl(v);val[++tot]=v; pref=lca(x,y); if(x!=pref)dfs(x,x,pref,tot); if(y!=pref)dfs(y,y,pref,tot); printf("%lld ",val[tot]); } if(op==2) { int p,c; read(p);read(c); e[fc[p]].w=c;e[fc[p]+1].w=c; } } } int main() { read(n);read(q); for(int i=1;i<n;i++) { int u,v; ll w; read(u);read(v);readl(w); add(u,v,w);fc[i]=cnt; add(v,u,w); } pre(1,0); solve1();return 0; }