码迷,mamicode.com
首页 > 其他好文 > 详细

【LCT】BZOJ3091 城市旅行

时间:2018-01-13 00:22:45      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:gre   center   3.1   图片   mem   nbsp   iostream   height   sam   

3091: 城市旅行

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1927  Solved: 631
[Submit][Status][Discuss]

Description

技术分享图片

Input

技术分享图片

Output

技术分享图片

Sample Input

4 5
1 3 2 5
1 2
1 3
2 4
4 2 4
1 2 4
2 3 4
3 1 4 1
4 1 4

Sample Output

16/3
6/1

HINT

对于所有数据满足 1<=N<=50,000 1<=M<=50,000 1<=Ai<=10^6 1<=D<=100 1<=U,V<=N

题解

这题和BZOJ2752类似,只不过那个是在序列上而这个在链上,所以没做过2752的话可以先看看这里

我们发现每次询问其实就是算每个点对答案的贡献/C(n+1,2),也就是/(n+1)*n/2

所以每次只需要单独算每个点的贡献即可

然后每个点对答案的贡献就是a[i]*i*(n-i+1)

所以我们维护一个sum,一个siz,一个L=a[i]*i,一个R=a[i]*(n-i+1)

转移挺好想的(逃

代码(WA???)

//by 减维
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<bitset>
#include<set>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<ctime>
#include<algorithm>
#define ll long long
#define il inline
#define rg register
#define db double
#define mpr make_pair
#define maxn 70005
#define inf (1<<30)
#define eps 1e-8
#define pi 3.1415926535897932384626
using namespace std;

inline int read()
{
    int ret=0;bool fla=0;char ch=getchar();
    while((ch<0||ch>9)&&ch!=-)ch=getchar();
    if(ch==-){fla=1;ch=getchar();}
    while(ch>=0&&ch<=9){ret=ret*10+ch-0;ch=getchar();}
    return fla?-ret:ret;
}

ll n,m,fa[maxn],son[maxn][2],siz[maxn],val[maxn],sum[maxn],rev[maxn],mar[maxn],L[maxn],R[maxn],ans[maxn];

il ll gcd(ll x,ll y){return y==0?x:gcd(y,x%y);}
il bool pdp(int x){return son[fa[x]][1]==x;}
il bool isrt(int x){return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}
il void rever(int x){rev[x]^=1;swap(son[x][0],son[x][1]);swap(L[x],R[x]);}

il void upda(int x)
{
    siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;
    sum[x]=sum[son[x][0]]+sum[son[x][1]]+val[x];
    ans[x]=ans[son[x][0]]+ans[son[x][1]]+val[x]*(siz[son[x][0]]+1)*(siz[son[x][1]]+1)+L[son[x][0]]*(siz[son[x][1]]+1)+R[son[x][1]]*(siz[son[x][0]]+1);
    L[x]=L[son[x][0]]+L[son[x][1]]+val[x]*(siz[son[x][0]]+1)+sum[son[x][1]]*(siz[son[x][0]]+1);
    R[x]=R[son[x][1]]+R[son[x][0]]+val[x]*(siz[son[x][1]]+1)+sum[son[x][0]]*(siz[son[x][1]]+1);
}

il void add(int x,ll y)
{
    mar[x]+=y;
    val[x]+=y;
    sum[x]+=y;
    ans[x]+=y*(siz[x]+1)*(siz[x]+2)*siz[x]/6;
    L[x]+=y*(siz[x]+1)*siz[x]/2;
    R[x]+=y*(siz[x]+1)*siz[x]/2;
}

il void pdn(int x)
{
    if(rev[x])
    {
        if(son[x][0]) rever(son[x][0]);
        if(son[x][1]) rever(son[x][1]);
        rev[x]=0;
    }
    if(mar[x])
    {
        if(son[x][0]) add(son[x][0],mar[x]);
        if(son[x][1]) add(son[x][1],mar[x]);
        mar[x]=0;
    }
}

il void pd(int x){if(!isrt(x)) pd(fa[x]);pdn(x);}

il void rot(int x)
{
    int f=fa[x],g=fa[f],o=pdp(x);
    if(!isrt(f)) son[g][pdp(f)]=x;fa[x]=g;
    son[f][o]=son[x][!o];fa[son[f][o]]=f;
    son[x][!o]=f;fa[f]=x;
    upda(f),upda(x);
}

il void splay(int x)
{
    pd(x);
    for(;!isrt(x);rot(x))
        if(!isrt(fa[x])) rot(pdp(fa[x])==pdp(x)?fa[x]:x);
}

il void acc(int x)
{
    for(int y=0;x;y=x,x=fa[x])
        splay(x),son[x][1]=y,upda(x);
}

il int find(int x)
{
    acc(x);splay(x);
    while(son[x][0]) pdn(x),x=son[x][0];
    return x;
}

il void bert(int x){acc(x);splay(x);rever(x);}
il void spli(int x,int y){bert(x);acc(y);splay(y);}
il void cut(int x,int y){spli(x,y);fa[x]=son[y][0]=0;upda(y);}
il void link(int x,int y){bert(x);fa[x]=y;}

void dfs(int x)
{
    if(son[x][0]) dfs(son[x][0]);
    printf("%d ",x);
    if(son[x][1]) dfs(son[x][1]);
}

void dfs2(int x)
{
    if(son[x][0]) dfs2(son[x][0]);
    printf("%d ",sum[x]);
    if(son[x][1]) dfs2(son[x][1]);
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;++i) val[i]=read();
    for(int i=1,x,y;i<n;++i) x=read(),y=read(),link(x,y);
    for(int i=1,op,x,y,d;i<=m;++i)
    {
        op=read();x=read();y=read();
        if(op==1){
            if(find(x)==find(y)) cut(x,y);
        }else if(op==2){
            if(find(x)!=find(y)) link(x,y);
        }else if(op==3){
            d=read();
            spli(x,y);add(y,d);
        }else{
            if(find(x)!=find(y)) puts("-1");
            else spli(x,y),printf("%lld/%lld\n",ans[y]/gcd(ans[y],siz[y]*(siz[y]+1)/2),(siz[y]+1)*siz[y]/2/gcd(ans[y],siz[y]*(siz[y]+1)/2));
        }
    }
    return 0;
}

 

【LCT】BZOJ3091 城市旅行

标签:gre   center   3.1   图片   mem   nbsp   iostream   height   sam   

原文地址:https://www.cnblogs.com/rir1715/p/8277830.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!