2843: 极地旅行社

题目链接

题解:

对于第一个操作我们可以用并查集来搞,

然后离线+树链剖分+树状数组,

感觉不是很难想,后来看了看题解发现全都用lct,蒟蒻lct太弱QWQ,只好乱搞了。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100010;
const int M=30010;
int n,m;
int v[M],f[M];
char s[N],s1[20];
int x[N],y[N];
struct node{
    int x,y,next;
}sa[N*2];int len=1,first[M];
bool tf[M];
int bit[N];
int lowbit(int x)
{
    return x&-x;
}
void add(int x,int y)
{
    while(x<=n)
    {
        bit[x]+=y;
        x+=lowbit(x);
    }
}
int getsum(int x)
{
    int sum=0;
    while(x>=1)
    {
        sum+=bit[x];
        x-=lowbit(x);
    }
    return sum;
}
int findfa(int x){
    int a=x,c;
    while(x!=f[x])x=f[x];
    while(x!=(c=f[a]))f[a]=x,a=c;
    return x;
}
void ins(int x,int y)
{
    len++;
    sa[len].x=x;
    sa[len].y=y;
    sa[len].next=first[x];
    first[x]=len;
}
int dep[M],son[M],size[M],fa[M];
void dfs1(int x,int pa)
{
    size[x]=1;
    fa[x]=pa;
    for(int i=first[x];i!=-1;i=sa[i].next)
    {
        int y=sa[i].y;
        if(y!=pa)
        {
            dep[y]=dep[x]+1;
            dfs1(y,x);
            size[x]+=size[y];
            if(size[son[x]]<size[y]) son[x]=y;
        }
    }
}
int top[M],id[M],idn=0;
void dfs2(int x,int tp)
{
    //printf("%d %d\n",x,tp);
    //system("pause\n");
    top[x]=tp;
    id[x]=++idn;
    add(id[x],v[x]);
    if(son[x]) dfs2(son[x],tp);
    for(int i=first[x];i!=-1;i=sa[i].next)
    {
        int y=sa[i].y;
        if(y!=fa[x]&&y!=son[x])
        {
            dfs2(y,y);
        }
    }
}
int solve(int x,int y)
{
    /*int tx=top[x],ty=top[y],s=0;
    while(tx!=ty)
    {
        if(dep[x]>dep[y]) swap(x,y),swap(tx,ty);
        s+=getsum(id[y])-getsum(id[ty]-1);
        y=fa[ty];ty=top[y];
    }
    if(dep[x]>dep[y]) swap(x,y);
    s+=getsum(id[y])-getsum(id[x]-1);
    return s;*/
    int a=top[x],b=top[y],c,s=0;
    while(a!=b){
        if(dep[a]<dep[b]){
            s+=getsum(id[y])-getsum(id[b]-1);
            y=fa[b];b=top[y];
        }else{
            s+=getsum(id[x])-getsum(id[a]-1);
            x=fa[a];a=top[x];
        }
    }
    if(dep[x]<dep[y])s+=getsum(id[y])-getsum(id[x]-1);
    else s+=getsum(id[x])-getsum(id[y]-1);
    return s;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)f[i]=i;
    for(int i=1;i<=n;i++) scanf("%d",&v[i]);
    memset(first,-1,sizeof(first));
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%s",s1);
        scanf("%d%d",&x[i],&y[i]);
        s[i]=s1[0];
        if(s1[0]=='b')
        {
            int tx=findfa(x[i]),ty=findfa(y[i]);
            if(tx!=ty)
            {
                f[tx]=ty;
                ins(x[i],y[i]);ins(y[i],x[i]);
            }
        }
    }
    memset(bit,0,sizeof(bit));
//  for(int i=1;i<=n;i++) printf("%d\n",fa[i]);
    for(int i=1;i<=n;i++)
    if(!tf[findfa(i)])
    {
        tf[findfa(i)]=true;
        dfs1(i,0);dfs2(i,i);//printf("@\n");printf("!");
    }
//  printf("!");
    for(int i=1;i<=n;i++) f[i]=i;
    for(int i=1;i<=m;i++)
    {
        if(s[i]=='b')
        {
            int tx=findfa(x[i]),ty=findfa(y[i]);
            if(tx!=ty) f[tx]=ty,printf("yes\n");
            else printf("no\n");
        }
        else if(s[i]=='p')
        {
            int yu=y[i]-v[x[i]];
            v[x[i]]+=yu;
            add(id[x[i]],yu);
        }
        else
        {
            int tx=findfa(x[i]),ty=findfa(y[i]);
            if(tx!=ty)printf("impossible\n");
            else printf("%d\n",solve(x[i],y[i]));
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值