2025.8.16模拟赛

T1

判断是否存在一棵树,满足它有 \(a\) 个一度点和 \(b\) 个三度点,如果存在请给出一个节点数不超过 \(2000\) 的构造,否则输出 \(0\)
\(0\le a,b\le 200\)

  • \(a=0,b=0\) 直接输出 \(1\)
  • \(a=0,b\not = 0\) 显然不可能。
  • \(a\not = 0,b=0\)\(a=1\)\(a=3\) 时无解,其余输出一个菊花即可。

剩余 \(a,b>0\)

考虑将所有 \(b=3\) 组成一个二叉树,叶子结点用 \(a\) 填充。如果 \(a<b+2\) 无解,等于的情况根节点度数为 \(3\),构成一棵二叉树。可以发现 \(a=b+3\) 无解,\(a>b+3\) 直接二叉树,多余的 \(a\) 加到根节点作为菊花即可。

赛时代码
#include<bits/stdc++.h>
using namespace std;
const int N=1000;
int a,b;
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>a>>b;
    if(!a&&!b)return cout<<1,0;
    if(!a&&b)return cout<<0,0;
    if(a&&!b){
        if(a==1||a==3)cout<<0;
        else{
            cout<<a+1<<'\n';
            for(int i=2;i<=a+1;++i)
                cout<<1<<' '<<i<<'\n';
        }return 0;
    }if(a<b+2)return cout<<0,0;
    if(a==b+2){
        cout<<a+b<<'\n';
        for(int i=1,s=1;i<=b;++i){
            if(i==1)cout<<i<<' '<<++s<<'\n',
                    cout<<i<<' '<<++s<<'\n',
                    cout<<i<<' '<<++s<<'\n';
            else    cout<<i<<' '<<++s<<'\n',
                    cout<<i<<' '<<++s<<'\n';
        }return 0;
    }if(a==b+3)return cout<<0,0;
    cout<<a+b+1<<'\n';
    int s=1;
    for(int i=1;i<=b+1;++i)
        cout<<i<<' '<<++s<<'\n',
        cout<<i<<' '<<++s<<'\n';
    a-=b+2;
    for(int i=1;i<=a;++i)
        cout<<1<<' '<<++s<<'\n';
    return 0;
}

T2

有一张 \(n\) 个点 \(m\) 条边的有向图,每条边上有一个正整数边权,要顺着图上的有向边从 \(1\) 号点走到 \(n\) 号点。假设你经过的边边权依次为 \(w_1 ,w_2\dots w_t\),则你的疲惫程度为 \(\max_{i=1}^t iw_i\)。求最小疲惫程度的路径长。
\(1\le n,m\le 3\times 10^5\)

二分答案,然后记录一下每个点最早什么时候到,移动的时候判一下与 \(mid\) 大小关系即可。

赛时代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3e5+5,F=0x3f3f3f3f;
int n,m,dis[N];
int head[N],tot;queue<int> q;
struct edge{int v,w,nxt;}e[N];
void add(int u,int v,int w){
    e[++tot]=(edge){v,w,head[u]},head[u]=tot;
}bool check(ll x){
    for(int i=2;i<=n;++i)
        dis[i]=F;
    q.push(1);
    while(q.size()){
        int u=q.front();q.pop();
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v,w=e[i].w;
            if(dis[v]==F&&1ll*w*(dis[u]+1)<=x)
                dis[v]=dis[u]+1,q.push(v);
        }
    }return dis[n]!=F;
}signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1,u,v,w;i<=m;++i)
        cin>>u>>v>>w,add(u,v,w);
    ll l=0,r=3e14;
    while(l<r){
        ll mid=l+r>>1;
        if(check(mid))r=mid;
        else l=mid+1;
    }cout<<r<<'\n';
    return 0;
}

T3

一个 \(n\) 个点 \(m\) 条边的简单无向连通图,点从 \(0\sim n−1\) 编号,现在你需要删掉若干条边,最大化度数为奇数的点的个数。并给出构造,即输出一个长度为 m 的 01 串,1表示保留这个边,0表示删掉这个边,输出字典序最大的方案。
部分分:\(m=n-1\)\(n\le 2000\)
100pts \(1\le n\le 600000,n-1\le m\le 900000\)

赛时犯糖了。认为最大化奇点个数是用 dp 做,然后若强制一条边保留答案不变那么就可选,按顺序贪,每次做 dp。。。然后想到了对于图除最大生成树外都可选而树上还要做 dp。然后获得了 60pts。hehe

会发现对于树的情况,\(n\) 为偶数每个点由其连接父亲的那条边决定最终奇偶性,然后根节点必为奇点,方案是固定的;\(n\) 为奇数根节点必不为奇点,而对于不同的根共有 \(n\) 种结果,我们要最优化字典序。

对于有奇数个点的树,将其成为奇块,若有一条边的一端通向奇块,那么其等效于偶块。

维护奇偶性直接看最后一位的异或和。考虑分裂联通块从前到后考虑,如果不是生成树边直接选,并将两边块的块异或上 \(1\)。如果是树边。若两边都不是奇块,那么是真的无能为力。若至少一个奇块,那么直接选,剩下的留给后面的边考虑。再将块分出去。

赛后代码
#include<bits/stdc++.h>
#define eb emplace_back
using namespace std;
const int N=9e5+5;
int n,m,k,sum[N],deg[N];
int id[N],x[N],y[N];
vector<int> a[N],b[N];
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;++i)
        id[i]=i,a[i].eb(i);
    for(int i=1;i<=m;++i)
        cin>>x[i]>>y[i],++x[i],++y[i];
    for(int i=m;i>=1;--i){
        int u=id[x[i]],v=id[y[i]];
        if(u!=v){
            if(a[u].size()>a[v].size())swap(u,v);
            b[i]=a[u];a[u].clear();
            for(int x:b[i])a[v].eb(x),id[x]=v;
        }
    }sum[k=1]=n&1;
    for(int i=1;i<=n;++i)
        id[i]=1;
    for(int i=1;i<=m;++i){
        if(b[i].empty()){cout<<1;deg[x[i]]^=1,deg[y[i]]^=1;continue;}
        int u=id[x[i]],tmp=0;
        for(int x:b[i])tmp^=deg[x];
        if(!(tmp&1)&&!(sum[u]&1))cout<<0;
        else cout<<1,deg[x[i]]^=1,deg[y[i]]^=1,tmp^=1;
        sum[u]^=tmp;sum[++k]=tmp;
        for(int x:b[i])id[x]=k;
    }
    return 0;
}

T4

有一个 \(r\times c\) 的平面。有 \(n\) 个矩形在平面上和 \(q\) 个查询。每个查询给你一个矩形,询问这个矩形与给定的 \(n\) 个矩形相交的面积之并的面积。也可以认为是这 \(n\) 个矩形并的整个图形与给定矩形的交的面积。
\(1\le n,q\le 10^5\)。部分数据强制在线。

离线做这玩意是区间历史和,线段树维护一堆魔法懒标记。在线就是可持久化,十分的恐怖。没写。

posted @ 2025-08-20 21:05  zzy0618  阅读(14)  评论(0)    收藏  举报