首页 > 其他分享 >2023NOIP A层联测31 T4 民主投票

2023NOIP A层联测31 T4 民主投票

时间:2023-11-15 15:36:25浏览次数:40  
标签:int 31 mid tot 2023NOIP edge maxn dfs T4

2023NOIP A层联测31 T4 民主投票

思维好题。

思路

首先可以设 \(s\) 每个人最多获得的票数,一开始所有点都把自己的票投给自己父亲。

如果一个点的票数超过 \(s\) 了,那么这个点肯定要把票分给他的父亲。

设 \(f_{u,s}\) 为 \(u\) 点在最多获得 \(s\) 票的情况下要向父亲分的票数(不包括一开始投的)。

如果 \(f_{1,s}\) 大于 \(0\) 表示无法每个点至多获得 \(s\),反之则可以。

可以二分求这个最小的 \(s\) 值。

点 \(u\) 获得的最多票数是 \(siz_u-1\) 票。

如果 \(siz_u-1>s\) 那么 \(u\) 肯定可以获胜。如果 \(siz_u-1<s\) 那么证明 \(f_{u,s}=0\),把 \(u\) 子树脱离原树不造成影响,即 \(u\) 子树内所以点投 \(u\) 无法影响最小值 \(s\),所以 \(siz_u-1<s\) 时,\(u\) 肯定无法获胜。

对于 \(siz_u-1=s\) 而言,\(f_{u,s}=1/0\)。

此时求 \(f_{1,s-1}\),\(f_{1,s-1}\) 必然大于 \(0\)。

如果 \(f_{1,s-1}=1\),则这一票肯定是通过某个 \(siz_u-1=s\) 的点传上来,由于点 \(u\) 在被取的情况下不会向上传票,所以点 \(u\) 可以获胜,即去掉 \(u\) 的后代后,\(f_{1,s-1}=0\)。

如果 \(f_{1,s-1}>1\),肯定是有多个上文分析的点会传票到根,\(u\) 节点不能获胜。

CODE

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e6+5;

struct node
{
    int to,nxt;
}edge[maxn];

int n,tot=0;
int head[maxn],f[maxn],sz[maxn],ans[maxn];

bool fg;

inline void add(int x,int y)
{
    tot++;
    edge[tot].to=y;
    edge[tot].nxt=head[x];
    head[x]=tot;
}

inline void clr()
{
    tot=0;
    for(int i=0;i<=n;i++) head[i]=0,edge[i]={0,0};
}
inline void dfs_sz(int u)
{
    sz[u]=1;
    for(int i=head[u];i;i=edge[i].nxt) dfs_sz(edge[i].to),sz[u]+=sz[edge[i].to];
}
inline void dfs_ans(int u,int mid)
{
    f[u]=0;
    for(int i=head[u];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        dfs_ans(v,mid);
        f[u]+=f[v]+1;
        if(u==1&&f[u]-mid>0&&fg) return ;
    }
    f[u]=max(0,f[u]-mid);
}
inline void dfs_change(int u,int mid)
{
    if(sz[u]-1==mid){ans[u]=1;return;}
    for(int i=head[u];i;i=edge[i].nxt) if(f[edge[i].to]>0) dfs_change(edge[i].to,mid);
}

int main()
{
    int _;
    scanf("%d",&_);
    while(_--)
    {
        fg=1;
        scanf("%d",&n);
        clr();
        for(int i=2;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            add(x,i);
        }
        dfs_sz(1);
        int l=1,r=n,x=0;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            dfs_ans(1,mid);
            if(f[1]==0) r=mid-1,x=mid;
            else l=mid+1;
        }
        for(int i=1;i<=n;i++) {ans[i]=(sz[i]-1>x);}
        fg=0;
        dfs_ans(1,x-1);
        if(f[1]==1) dfs_change(1,x);
        for(int i=1;i<=n;i++) printf("%d",ans[i]);
        putchar('\n');
    }
}

标签:int,31,mid,tot,2023NOIP,edge,maxn,dfs,T4
From: https://www.cnblogs.com/binbinbjl/p/17833947.html

相关文章

  • 20231109 我如何看待命题:计算机不能解决那些计算机外部世界无解决方法的问题
    “解释为什么计算机不能解决那些计算机外部世界无解决方法的问题”是《计算机科学导论》第一章的第一道课后习题,以下是我的回答:在2023年的今天,我并不完全认同这个问题预设的命题,即“计算机不能解决那些计算机外部世界无解决方法的问题”(以下简称“命题A”)。1、什么是“计算机”......
  • frps: 2023/11/15 10:49:24 http: Accept error: accept tcp [::]:7650: accept4: too
    0.错误信息表明frps服务在接受传入连接时遇到了问题,特别是与端口7750相关的错误,具体错误为"accepttcp[::]:7750:accept4:toomanyopenfiles",意味着打开文件数目过多。这种错误通常发生在系统达到文件描述符的打开数目限制时。在类Unix操作系统中,每个进程都有同时可以......
  • Filebeat 仅收集命名规则为 myapp_20231114.log 这种当月产生的日志,以及 myapp.log 新
    Filebeat仅收集命名规则为myapp_20231114.log这种当月产生的日志,以及myapp.log新产生的当天的日志,可以通过以下配置来实现:filebeat.inputs:-type:logenabled:truepaths:-/data/myapp/logs/myapp_{{now|date:'yyyyMM'}}*.log-/data/myapp/logs/m......
  • P3160 [CQOI2012] 局部极小值
    [CQOI2012]局部极小值-洛谷题目详情-[cqoi2012]局部极小值-BZOJbyHydroOJ这题不值得单独写一个博客的,但我竟然没想出来,所以还是写吧\(QwQ\)又是我不擅长的找性质。性质:从小到大填数。当一个非局部最小值周围的所有局部最小值格子都被填了数时,这个位置才能填数。......
  • 2023NOIP A层联测30 总结
    2023NOIPA层联测30总结题目T1草莓列车\(n\leq10^5,m\leq10^7\)赛时思路一开始看错\(m\)数据范围,以为\(O(m\logm)\)可以过,后来发现问题以后,集中在考虑线段树之类的\(\log\)级别的算法维护序列,或者线段区间,一直没有想过ST表相关数据结构,于是最后只有60。赛后......
  • 20231114打卡
    今天学习了数据结构练习了最小生成树算法kruskal和最短路径dijkstra和floyd算法#defineMAX10000000#include<iostream>usingnamespacestd;structGraph{ int**arc; char*vex; intvexnum; intarcnum;};structEdge{ intstart,end,weight;};Edge*cre......
  • 洛谷 P1931 题解
    三倍经验P1931UVA436SP9340题意给你\(n(n\le30)\)种货币及\(m\)种汇率,问是否出现套利的情况。怎么没给\(m\)的范围啊思路首先把汇率抽象成一张图。容易发现,若一个单位的某种货币经过一个环获得了大于一的代价,说明出现了套利。具体来说,考虑Floyd,若$\existsi\in......
  • 2023NOIP A层联测31总结
    2023NOIPA层联测31总结\(T1\)暴力操作:给你一个长度为\(n\)的序列\(a\),你可以花费\(c_x\)使得\(a_i\)变为\([a_i/x]\),你总共有\(k\)元。为最终序列的中位数最小是多少。保证\(n\)为奇数。\(n,m\le5*10^5\)首先想到了二分一个答案,因为只要使得前\((n+1......
  • 231114校内模拟赛
    T1平凡原题链接首先,我们容易发现直接求\(A\)不是最小的子序列的排列的个数有些困难#include<bits/stdc++.h>#definemod998244353#defineN1000010#defineintlonglongusingnamespacestd;intn,k,a[N],t[N],vis[N],ans,all,pos;signedmain(){ freopen("ordina......
  • YCOJ734 [ 20231114 NOIP 模拟赛 T3 ] 二次函数
    题意给定\(n\)个形如\(f(x)=(x-m)^2+k\)的二次函数。\(1,m,k\)表示加入一个顶点位\((m,k)\)的二次函数。\(2,x,t\)表示删除所有\(f(x)\let\)的二次函数。求每次操作结束后还剩余几个二次函数。Sol注意到题中二次系数为\(1\),这就意味着每一个函......