bzoj3712: [PA2014]Fiolki
很神的题啊,转换模型构造树
对于一组反应,他们的优先级应该是反应时间和反应顺序
如何搞到反应的时间?
我们可以这样做:对于一组倾倒,新建一个点,连向这两个瓶子,y代表的瓶子更新为这个点
那么深度越大,优先级是越高的
维护这样的森林即可
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } struct node { int x,y,next; }a[410000];int len,last[410000]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int dep[410000]; int Bin[30],f[30][410000]; int LCA(int x,int y) { if(dep[x]<dep[y])swap(x,y); for(int i=23;i>=0;i--) if(dep[x]-dep[y]>=Bin[i])x=f[i][x]; if(x==y)return x; for(int i=23;i>=0;i--) if(dep[x]>=Bin[i]&&f[i][x]!=f[i][y])x=f[i][x],y=f[i][y]; return f[0][x]; } int cnt,bel[410000]; void dfs(int x) { bel[x]=cnt; for(int i=1;Bin[i]<=dep[x];i++)f[i][x]=f[i-1][f[i-1][x]]; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; f[0][y]=x; dep[y]=dep[x]+1; dfs(y); } } int g[210000],pos[210000];bool isrt[410000]; struct query { int x,y,k1,k2; query(){} query(int X,int Y,int K1,int K2){x=X,y=Y,k1=K1,k2=K2;} }q[510000];int qlen; bool cmp(query q1,query q2){return q1.k1==q2.k1?q1.k2<q2.k2:q1.k1>q2.k1;} int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int n,m,K,x,y; n=read(),m=read(),K=read(); for(int i=1;i<=n;i++)g[i]=read(),pos[i]=i; len=0;memset(last,0,sizeof(last)); memset(isrt,true,sizeof(isrt)); for(int i=1;i<=m;i++) { x=read(),y=read(); ins(n+i,pos[x]),isrt[pos[x]]=false; ins(n+i,pos[y]),isrt[pos[y]]=false; pos[y]=n+i; } Bin[0]=1;for(int i=1;i<=25;i++)Bin[i]=Bin[i-1]*2; memset(bel,0,sizeof(bel)); for(int i=n+1;i<=n+m;i++) if(isrt[i]==true)dep[i]=0,cnt++,dfs(i); for(int i=1;i<=K;i++) { x=read(),y=read(); if(bel[x]==bel[y]&&bel[x]!=0) { int lca=LCA(x,y); q[++qlen]=query(x,y,dep[lca],i); } } sort(q+1,q+qlen+1,cmp); LL ans=0; for(int i=1;i<=K;i++) { x=q[i].x,y=q[i].y; if(bel[x]==bel[y]&&bel[x]!=0) { int mn=min(g[x],g[y]); g[x]-=mn,g[y]-=mn; ans+=2*mn; } } printf("%lld\n",ans); return 0; }
pain and happy in the cruel world.