CodeForces 263E

基本思想是
预处理所有点的度数,
对于每个点预处理出所有和它相邻并且度数比它大的点
集,
每个点集大小为 (n)
每次操作 (n)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<cmath>
#include<map>
using namespace std;
const int N=50000+100;
const int M1=150000+100;
const int M=250000+100;
int fi[N];
int op[M],uu[M],vv[M];
int n,m,o,q;
int aa[M1],bb[M1];

vector<int> ve[N],we[N];
#define pb push_back
#define pii pair<int,int>
map<pii,int> mp;

int du[N];
void pri(int xx[N],int n){
    for(int i=0;i<n;i++){
        printf("%d ",xx[i]);
    }printf("\n");
}
void scc(){
    scanf("%d",&o);
    for(int i=0;i<o;i++){
        scanf("%d",&fi[i]);
    }
    //pri(fi,o);
    for(int i=0;i<m;i++){
        int a,b;scanf("%d%d",&a,&b);
        if(a>b)swap(a,b);
        aa[i]=a,bb[i]=b;
    }
    //pri(aa,m);
    //pri(bb,m);
    char ss[10];
    for(int i=0;i<q;i++){
        scanf("%s",ss);
        if(ss[0]=='O'){
            op[i]=0;scanf("%d",&uu[i]);
        }
        if(ss[0]=='F'){
            op[i]=1;scanf("%d",&uu[i]);
        }
        if(ss[0]=='A'){
            op[i]=2;scanf("%d%d",&uu[i],&vv[i]);
            if(uu[i]>vv[i])swap(uu[i],vv[i]);
        }
        if(ss[0]=='D'){
            op[i]=3;scanf("%d%d",&uu[i],&vv[i]);
            if(uu[i]>vv[i])swap(uu[i],vv[i]);
        }
        if(ss[0]=='C'){
            op[i]=4;scanf("%d",&uu[i]);
        }
    }
    //pri(op,q);
}

void sc(){
    scc();
    for(int i=1;i<=n;i++){
        ve[i].clear();we[i].clear();
    }
    mp.clear();
    memset(du,0,sizeof(du));
    for(int i=0;i<m;i++){
        int a=aa[i],b=bb[i];
        if(mp[pii(a,b)])continue;
        mp[pii(a,b)]=1;
        du[a]++;du[b]++;
    }
    for(int i=0;i<q;i++)if(op[i]==2){
        int a=uu[i],b=vv[i];
        if(mp[pii(a,b)])continue;
        mp[pii(a,b)]=1;
        du[a]++;du[b]++;
    }
    //pri(du,n+1);
    mp.clear();
    for(int i=0;i<m;i++){
        int a=aa[i],b=bb[i];
        if(mp[pii(a,b)])continue;
        mp[pii(a,b)]=1;
        //printf("%d %d\n",a,b);
        if(du[b]>=du[a]){
            ve[a].pb(b);
            we[a].pb(1);
        }
        else {
            ve[b].pb(a);
            we[b].pb(1);
        }
    }

    for(int i=0;i<q;i++)if(op[i]==2){
        int u=uu[i],v=vv[i];
        if(mp[pii(u,v)])continue;
        mp[pii(u,v)]=1;
        //printf("%d %d\n",u,v);
        if(du[u]>=du[v]){
            ve[v].pb(u);
            we[v].pb(0);
        }
        else {
            ve[u].pb(v);
            we[u].pb(0);
        }
    }
}

int ans[N];
void up(int u,int x){
    for(int j=0;j<ve[u].size();j++)if(we[u][j]){
        int v=ve[u][j];
        //printf("%d %d %d %d\n",u,v,x,j);
        ans[v]+=x;
    }
}

int on[N];
void cha(int u,int v){
    for(int j=0;j<ve[u].size();j++)if(ve[u][j]==v){
        if(on[u]){
            if(we[u][j]){
                ans[v]--;
            }
            else {
                ans[v]++;
            }
        }
        we[u][j]=!we[u][j];
        return ;
    }
}

void que(int u){
    int cnt=ans[u];
    for(int j=0;j<ve[u].size();j++)if(we[u][j]){
        int v=ve[u][j];
        if(on[v])cnt++;
    }
    printf("%d\n",cnt);
}

void getans(){
    memset(on,0,sizeof(on));
    for(int i=0;i<o;i++){
        on[fi[i]]=1;
        up(fi[i],1);
    }
    //pri(ans,n+1);
    for(int i=0;i<q;i++){
        if(op[i]==0){
            on[uu[i]]=1;
            up(uu[i],1);
        }
        if(op[i]==1){
            on[uu[i]]=0;
            up(uu[i],-1);
        }
        if(op[i]==2){
            cha(uu[i],vv[i]);
            cha(vv[i],uu[i]);
        }
        if(op[i]==3){
            cha(uu[i],vv[i]);
            cha(vv[i],uu[i]);
        }
        if(op[i]==4){
            que(uu[i]);
        }
    }
    //pri(op,q);
}

int main(){
    #ifdef DouBi
    freopen("in.cpp","r",stdin);
    #endif // DouBi
    while(scanf("%d%d%d",&n,&m,&q)!=EOF){
        sc();
        memset(ans,0,sizeof(ans));
        getans();
//        for(int i=1;i<=n;i++){
//            for(int j=0;j<ve[i].size();j++){
//                printf("%d ",ve[i][j]);
//            }printf(":%d\n",i);
//        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值