智算之道初赛第三场 - 高校组

A

简单模拟

想尽办法都没有优化到0ms

/*
    author:revolIA
    submit:;
*/
#include<bits/stdc++.h>
#pragma GCC optimize(3)
using namespace std;
typedef long long ll;
const int maxn = 1e5+7;
int n,L,A,B,opt,x,v;
int main(){
    scanf("%d%d%d%d",&n,&L,&A,&B);
    while(n--){
        scanf("%d",&opt);
        if(opt == 1){
            scanf("%d",&x);
        }else if(opt == 2){
            scanf("%d",&v);
        }else{
            if(A<=x&&x<=B&&v>=L){
                printf("%d\n",x);
            }else{
                printf("GG\n");
            }
        }
    }
    return 0;
}

B

易知,每人手里的牌都是唯一的,所以可以用标记数组

然后模拟队列即可

读入挂+o3优化,7ms

/*
    author:revolIA
    submit:;
*/
#include<bits/stdc++.h>
#pragma GCC optimize(3)
using namespace std;
typedef long long ll;
const int maxn = 1e5+7;
int A[maxn],B[maxn];
int qA[maxn<<5],qB[maxn<<5];
int lA,lB,rA,rB;
int cntA,cntB,cnt;
int ans,n;
pair<int,int> Tmp[maxn];
static char buf[maxn],*pa = buf,*pb = buf;
#define gc pa == pb&&(pb=(pa=buf)+fread(buf,1,maxn,stdin),pa==pb)?EOF:*pa++
inline int read(){
    register int x(0);
    register char c(gc);
    while(c<'0'||c>'9')c=gc;
    while('0'<=c&&c<='9'){
        x = (x<<1)+(x<<3)+(c^'0');
        c = gc;
    }
    return x;
}
int main(){
    //scanf("%d",&n);
    n = read();
    for(int i=0,x;i<4*n-2;i++){
        //scanf("%d",&x);
        x = read();
        if(i&1){
            if(A[x]){
                cntA--;
                A[x] = 0;
            }else{
                A[x] = i+1;
                cntA++;
            }
        }else{
            if(B[x]){
                cntB--;
                B[x] = 0;
            }else{
                B[x] = i+1;
                cntB++;
            }
        }
    }
    int tot = 0;
    for(int i=1;i<=n;i++){
        if(A[i]){
            Tmp[++tot] = make_pair(A[i],i);
        }
    }
    sort(Tmp+1,Tmp+1+tot);
    for(int i=0;i<tot;i++){
        qA[i] = Tmp[i-1].second;
    }
    rA = tot-1;
    tot = 0;
    for(int i=1;i<=n;i++){
        if(B[i]){
            Tmp[++tot] = make_pair(B[i],i);
        }
    }
    sort(Tmp+1,Tmp+1+tot);
    for(int i=0;i<tot;i++){
        qB[i] = Tmp[i].second;
    }
    rB = tot-1;
    while(cntA&&cntB){
        cnt++;
        if(cnt&1){
            while(!A[qA[lA]]&&lA<=rA){
                lA++;
            }
            --cntA;
            A[qA[lA]] = 0;
            if(B[qA[lA]]){
                --cntB;
                B[qA[lA]] = 0;
            }else{
                ++cntB;
                B[qA[lA]] = 1;
                qB[++rB] = qA[lA];
                lA++;
            }
        }else{
            while(!B[qB[lB]]&&lB<=rB){
                lB++;
            }
            --cntB;
            B[qB[lB]] = 0;
            if(A[qB[lB]]){
                --cntA;
                A[qB[lB]] = 0;
            }else{
                ++cntA;
                A[qB[lB]] = 1;
                qA[++rA] = qB[lB];
                lB++;
            }
        }
        //printf("%d %d\n",cntA,cntB);
    }
    printf("%d\n",cnt);
    return 0;
}

C

子树大小排序,然后就是贪心,要么按bfs贪心,要么按dfs贪心

bfs wa了,所以是dfs贪心正确(x

考虑优先每一层(bfs),这样可以使得这一层的找其父亲比较少,但是会导致大量的子节点的贡献增加。

由于树形结构,考虑越向下越大(参考指数爆炸,对于满二叉树来说),很容易hack掉了

所以dfs的可行

dfs参考dfs序,把树拍扁成一条线

快读+o3   46ms

/*
    author:revolIA
    submit:;
*/
#include<bits/stdc++.h>
#pragma GCC optimize(3)
using namespace std;
typedef long long ll;
const int maxn = 1e6+7;
static char buf[maxn],*pa = buf,*pb = buf;
#define gc pa == pb&&(pb=(pa=buf)+fread(buf,1,maxn,stdin),pa==pb)?EOF:*pa++
inline int read(){
    register int x(0);
    register char c(gc);
    while(c<'0'||c>'9')c=gc;
    while('0'<=c&&c<='9'){
        x = (x<<1)+(x<<3)+(c^'0');
        c = gc;
    }
    return x;
}
int head[maxn],Next[maxn],To[maxn];
int Tot;
void Add(int u,int v){
    To[++Tot] = v;
    Next[Tot] = head[u];
    head[u] = Tot;
}
int n,k;
int Size[maxn],vis[maxn];
pair<int,int> pll[maxn];
void dfs(int u){
    int cnt = 0;
    for(int i=head[u];i;i=Next[i]){
        dfs(To[i]);
        Size[u] += Size[To[i]];
    }
}
int main(){
    //scanf("%d%d",&n,&k);
    n = read();
    k = read();
    for(int i=1,x;i<=n;i++){
        if(i>=2){
            //scanf("%d",&x);
            x = read();
            Add(x,i);
        }
        Size[i] = 1;
    }
    dfs(1);
    long long ans = k;
    for(int i=1;i<=n;i++){
        int cnt = 0;
        for(int j=head[i];j;j=Next[j]){
            pll[++cnt] = make_pair(Size[To[j]],To[j]);
        }
        sort(pll+1,pll+1+cnt);
        long long gap = 1;
        for(int j=1;j<=cnt;j++){
            ans += k*gap;
            gap += Size[pll[j].second];
        }
    }
    printf("%lld\n",ans);
    return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值