【GDSOI2017第三轮模拟】Informatics Training(码农,平衡树)

6 篇文章 0 订阅
3 篇文章 0 订阅

Description

这里写图片描述

Solution

这题一看及时一道码农题。
肯定是平衡树。
但是c++可以直接用set做。
用给体力,颜色,每个组,序号,每组最小的刷题量开一个set。
然后搞一搞。
结果常数写的不好呗强行卡成暴力分。超了500ms,难得优化。

Code

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<set>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=2e5+7;
int i,j,k,l,t,n,m,ans,ans1,cas,x,y,num,u,v,xiao,r;
int f[maxn],e[maxn],g[maxn],z[maxn];
bool bz[maxn];
char s[5];
struct node{
    int x,w;
    bool friend operator<(node x,node y){
        return x.w<y.w||x.w==y.w&&x.x<y.x;
    }
}p,q,o;
multiset<node>a,b,A;
multiset<int>c[maxn],d;
multiset<node>:: iterator yi,er;
multiset<int>:: iterator ii;
int gf(int x){return(!f[x])?x:f[x]=gf(f[x]);}
void gx(int x){
    p.x=0,p.w=x;
    yi=a.lower_bound(p);p=*yi;
}
void gy(int y){
    q.x=0,q.w=y;
    er=b.lower_bound(q);q=*er;
}
void he(int x,int y){
    u=gf(x),v=gf(y);
    if(c[u].size()>c[v].size())swap(u,v);
    if(u!=v){
        f[u]=v;e[0]=0;
        for(ii=c[u].begin();ii!=c[u].end();ii++){
            t=*ii;e[++e[0]]=t;
            gy(t);o.x=t,o.w=q.x;
        }
        fo(i,1,e[0])c[u].erase(e[i]),c[v].insert(e[i]);
        g[v]+=g[u];
    }
}
int main(){
//  freopen("training.in","r",stdin);
//  freopen("training.out","w",stdout);
    freopen("fan.in","r",stdin);
    freopen("fan.out","w",stdout);
    for(scanf("%d",&cas);cas;cas--){
        scanf("%s",s+1);
        if(s[1]=='J'){
            scanf("%d%d",&x,&y);++num;
            p.x=x,p.w=num;a.insert(p);
            q.x=y,q.w=num;b.insert(q);
            o.x=num,o.w=y;A.insert(o);
            d.insert(num);
            c[num].insert(num);g[num]=y;
        }
        else if(s[1]=='P'){
            scanf("%d%d%d",&r,&x,&y);u=gf(r);g[u]+=y;
            gx(r);p.x-=x;
            gy(r);q.x+=y;
            a.erase(yi),b.erase(er);
            o.x=r,o.w=q.x-y;A.erase(o);
            if(p.x>0)a.insert(p),b.insert(q),o.w+=y,A.insert(o);
            else c[u].erase(r),d.erase(r),g[u]-=q.x;
        }
        else if(s[1]=='D'){
            scanf("%d%d%d",&r,&x,&y);u=gf(r);
            e[0]=0;g[u]+=c[u].size()*y;
            for(ii=c[u].begin();ii!=c[u].end();ii++){
                t=*ii;
                gx(t);p.x-=x;
                gy(t);q.x+=y;
                a.erase(yi),b.erase(er);
                o.x=q.w,o.w=q.x-y;A.erase(o);
                if(p.x>0)a.insert(p),b.insert(q),o.w+=y,A.insert(o);
                else e[++e[0]]=t,g[u]-=q.x;
            }
            fo(i,1,e[0])c[u].erase(e[i]),d.erase(e[i]);
        }
        else if(s[1]=='E'){
            scanf("%d",&r);u=gf(r);
            gx(r);a.erase(p);
            gy(r);b.erase(q);
            o.x=q.w,o.w=q.x;A.erase(o);
            c[u].erase(r);d.erase(r);g[u]-=q.x;
        }
        else if(s[1]=='M'){
            scanf("%d%d",&x,&y);
            he(x,y);
        }
        else if(s[1]=='C'){
            if(d.begin()==d.end())continue;
            ii=d.begin();x=*ii;ii=d.end();ii--;y=*ii;
            he(x,y);
        }
        else if(s[1]=='T'){
            xiao=(*A.begin()).w;e[0]=z[0]=0;
            while(1){
                o=*A.begin();
                if(d.begin()==d.end())break;
                if(o.w!=xiao)break;
                u=gf(o.x);
                p.w=o.x,p.x=xiao;a.erase(p);
                q.w=o.x,q.x=xiao;b.erase(q);
                c[u].erase(o.x);d.erase(o.x);g[u]-=xiao;
                A.erase(o);
            }
        }
        else{
            scanf("%d",&x);
            u=gf(x);ans=ans1=0;
            ans=c[u].size();
            printf("%d %d\n",ans,g[u]);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值