T1:

《弹珠游戏》

\(n\) 个人,\(3n\) 个弹珠,分别为 \(R,G,B\),每个人三种颜色分别取一个,不满意度为编号极差,求所有人不满意度和最小时的方案数。

壮压计数,至于之前每种颜色的个数有关,当当前为 \(R\) 时,前面若有 \(GB\) 则乘上其人数,否则若有 \(G\) 则乘上其人数,否则若有 \(B\) 则乘上其人数,否则乘上 \(0\) 的人数,之后更新对应人数。


#include<bits/stdc++.h>

using namespace std;

#define int long long
constexpr int N=3e5+5,mod=998244353;
int n,cnt[10],ans;
signed main(){
    freopen("A.in","r",stdin),freopen("A.out","w",stdout);
    ans=1;
    cin>>n;
    cnt[0]=n;
    n*=3;
    for(int i=1;i<=n;i++){
        char c;
        cin>>c;
        switch(c){
            case 'R':if(cnt[6])(ans*=cnt[6]--)%=mod;else if(cnt[4])(ans*=cnt[4]--)%=mod,cnt[5]++;else if(cnt[2])(ans*=cnt[2]--)%=mod,cnt[3]++;else (ans*=cnt[0]--)%=mod,cnt[1]++;break;
            case 'G':if(cnt[5])(ans*=cnt[5]--)%=mod;else if(cnt[4])(ans*=cnt[4]--)%=mod,cnt[6]++;else if(cnt[1])(ans*=cnt[1]--)%=mod,cnt[3]++;else (ans*=cnt[0]--)%=mod,cnt[2]++;break;
            case 'B':if(cnt[3])(ans*=cnt[3]--)%=mod;else if(cnt[2])(ans*=cnt[2]--)%=mod,cnt[6]++;else if(cnt[1])(ans*=cnt[1]--)%=mod,cnt[5]++;else (ans*=cnt[0]--)%=mod,cnt[4]++;break;
        }
    }
    cout<<ans;
    return 0;
}

T2:

《晚会》

定义一个三元组不合法,当且仅当出现 \(dis(i,j)<dis(i,k)\) 并且 \(dis(i,j)<dis(j,k)\) ,给出一些边,求合法时的 \(\sum_{i=1}^{n}\sum_{j=i+1}^{n}dis(i,j)\),或者无解。

对于一个三元组而言,新加入的边是另外两条边的较小值,于是找出最大生成树,再进行重构,若给出的边的瓶颈权值不等于边权则无解,两个子图不连通时两边只连边权为 \(1\) 的点即可。


#include<bits/stdc++.h>

using namespace std;

#define int long long
constexpr int N=6e5+5;
int n,m,ans,sz[N],fa[N][25],dep[N],lc[N],rc[N],val[N],num;
bool vis[N];
struct edge{int x,y,w;inline bool friend operator<(const edge&a,const edge&b){return a.w>b.w;}}e[N];
struct DSU{
    int f[N];
    inline void init(int n){for(int i=1;i<=n;i++)f[i]=i;}
    int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
}d;
void dfs(int x,int f){
    fa[x][0]=f;
    dep[x]=dep[f]+1;
    for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
    if(x<=n)return;
    dfs(lc[x],x);
    dfs(rc[x],x);
}
inline int LCA(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    for(int i=20;~i;i--)if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
    if(x==y)return x;
    for(int i=20;~i;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
void dfs0(int x,int f){
    if(x<=n)return sz[x]=1,void();
    dfs0(lc[x],x),dfs0(rc[x],x);
    sz[x]=sz[lc[x]]+sz[rc[x]];
    ans+=sz[lc[x]]*sz[rc[x]]*val[x];
    num+=sz[lc[x]]*sz[rc[x]];
}
inline void exkruskal(){
    sort(&e[1],&e[m+1]);
    d.init(n);
    int cnt=n;
    for(int i=1;i<=m;i++){
        int x=d.find(e[i].x),y=d.find(e[i].y);
        if(x==y)continue;
        vis[i]=1;
        val[++cnt]=e[i].w;
        d.f[x]=d.f[y]=d.f[cnt]=cnt;
        lc[cnt]=x,rc[cnt]=y;
    }
    for(int i=cnt;i;i--)if(!fa[i][0])dfs(i,0);
    for(int i=1;i<=m;i++){
        if(vis[i])continue;
        if(e[i].w<val[LCA(e[i].x,e[i].y)])cout<<-1,exit(0);
    }
    for(int i=cnt;i>n;i--)if(!fa[i][0])dfs0(i,0);
    ans+=n*(n-1)/2-num;
    cout<<ans;
}
signed main(){
    freopen("B.in","r",stdin),freopen("B.out","w",stdout);
    cin>>n>>m;
    for(int i=1;i<=m;i++)cin>>e[i].x>>e[i].y>>e[i].w;
    exkruskal();
    return 0;
}

T4:

《选举》

\(n\) 个城市和 \(m\) 个党派,每个城市 \(i\) 会将自己全部的 \(b_i\) 张票投给自己支持的党派 \(a_i\),每次询问城市区间 \([l,r]\) 和党派区间 \([vl,vr]\),求党派区间内最大的得票数量。

回滚莫队维护。


#include<bits/stdc++.h>

using namespace std;

#define int long long
constexpr int N=3e5+5;
int n,m,qq,bln[N],blm[N],a[N],b[N],cnt[N],ans[N],mx[N],rem[N],len,lem;
struct node{
    int id,l,r,vl,vr;
    inline bool friend operator<(const node&a,const node&b){return bln[a.l]==bln[b.l]?a.r<b.r:a.l<b.l;}
}q[N];
void add(int x){
    cnt[a[x]]+=b[x];
    rem[x]=mx[blm[a[x]]];
    mx[blm[a[x]]]=max(mx[blm[a[x]]],cnt[a[x]]);
}
inline void del(int x){
    cnt[a[x]]-=b[x];
    mx[blm[a[x]]]=rem[x];
}
inline void clear(int r){
    while(r&&cnt[a[r]])mx[blm[a[r]]]=0,cnt[a[r]]-=b[r],r--;
}
inline int query(int l,int r){
    int re=0;
    if(blm[l]==blm[r]){
        for(int i=l;i<=r;i++)re=max(re,cnt[i]);
        return re;
    }
    re=max(query(l,blm[l]*lem),query((blm[r]-1)*lem+1,r));
    for(int i=blm[l]+1;i<blm[r];i++)re=max(re,mx[i]);
    return re;
}
signed main(){
    freopen("D.in","r",stdin),freopen("D.out","w",stdout);
    cin>>n>>m>>qq;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++)cin>>b[i];
    for(int i=1;i<=qq;i++)cin>>q[i].l>>q[i].r>>q[i].vl>>q[i].vr,q[i].id=i;
    len=sqrt(n);
    for(int i=1;i<=n;i++)bln[i]=(i-1)/len+1;
    lem=sqrt(m);
    for(int i=1;i<=m;i++)blm[i]=(i-1)/lem+1;
    sort(&q[1],&q[qq+1]);
    int r=0;
    for(int i=1;i<=qq;i++){
        if(bln[q[i].l]!=bln[q[i-1].l])clear(r),r=min(bln[q[i].l]*len,n);
        while(r<q[i].r)add(++r);
        int lim=min(q[i].r,bln[q[i].l]*len);
        for(int j=q[i].l;j<=lim;j++)add(j);
        ans[q[i].id]=query(q[i].vl,q[i].vr);
        for(int j=lim;j>=q[i].l;j--)del(j);
    }
    for(int i=1;i<=qq;i++)cout<<ans[i]<<'\n';
    return 0;
}

这大概是我最后一篇题解了吧。
由于没有noip,再加上春季赛,还有消失的假期,未知的文化课,
我比赛根本没有认真打,许多人甚至连暴力都没有敲。

我和 \(Sakura\) 玩敲 \(01\) 串,他用小键盘敲 \(1\),我用大键盘敲 \(0\),显然是两人同时的,之后摩尔投票判断手速决定胜负。

我敲 \(0\) 的!

原文地址:http://www.cnblogs.com/safeng/p/16926070.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性