首页 > 其他分享 >P8819 [CSP-S 2022] 星战 (很厉害的随机化想法)

P8819 [CSP-S 2022] 星战 (很厉害的随机化想法)

时间:2024-03-26 17:11:07浏览次数:27  
标签:cnt 星战 int cin P8819 随机化 op else out

简化下题意
有n个点 m条单向边 每条边有激活和失活两种状态,一共有4中操作
1.失活一条 u->v 的边
2.失活终点是 v 的边
3.激活 u->v 的边
4.激活终点是 v 的边

问你每次修改后 每个点的出度是否都为 1.

50分的做法就是暴力修改,对于 1操作和3操作 都是 可以 o(1)解决,对于 2操作和 4操作需要 o(n)。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

typedef pair<int, int> pir;
const int N = 5e5 + 5;
int out[N];
std::vector<int> g[N];
map<int, int>mp[N];

void solve()
{
    int n, m;
    cin >> n >> m;
    int cnt = 0;
    for(int i = 1; i <= m; i++)
    {
        int u, v;
        cin >> u >> v;
        g[v].push_back(u);
        mp[v][u] = 1;
        out[u]++;
        if(out[u] == 1)cnt++;
        else if(out[u] == 2)cnt--;
    }
    int q;
    cin >> q;
    while(q--)
    {
        int op, u, v;
        cin >> op;
        if(op == 1)
        {
            cin >> u >> v;
            mp[v][u] = 0;
            out[u]--;
            if(out[u] == 0)cnt--;
            else if(out[u] == 1)cnt++;
        }
        else if(op == 2)
        {
            cin >> u;
            for(int v : g[u])
            {
                if(mp[u][v])
                {
                    out[v]--;
                    if(out[v] == 0)cnt--;
                    else if(out[v] == 1)cnt++;
                    mp[u][v] = 0;
                }
            }
        }
        else if(op == 3)
        {
            cin >> u >> v;
            mp[v][u] = 1;
            out[u]++;
            if(out[u] == 1)cnt++;
            else if(out[u] == 2)cnt--;
        }
        else
        {
            cin >> u;
            for(int v : g[u])
            {
                if(mp[u][v] == 0)
                {
                    out[v]++;
                    if(out[v] == 1)cnt++;
                    else if(out[v] == 2)cnt--;
                    mp[u][v] = 1;
                }
            }
        }
        if(cnt == n)cout << "YES\n";
        else cout << "NO\n";
    }
}

int main()
{
    // freopen("data.in", "r", stdin);
    // freopen("data.out", "w", stdout);
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);

    solve();
}

发现时间复杂度的瓶颈在于 2操作 和 4操作. 这个复杂度在维护出度的时候是很难避免的。

发现如果维护入度,那么对于4个操作都复杂度都是 o(1).
当符合每个点的出度都为 1 时,那么出度 总和就是 n,入度总和也是 n。
入度为 n 只是符合题目的一个 必要条件。
本题就是使用随机化使得这个必要条件无限接近充分必要条件。

具体做法是 对每个点i赋一个随机的权值 w[i].
对于每个点u的入度和就是

\[r[u]=\sum_{v \in u} w[v] \]

现在只要保证 $$(\sum_{i=1}^n r[i]) == (\sum_{i=1}^n w[i])$$
既能保证当前每个点的出度为 1

点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

typedef pair<int, int> pir;
const int N = 5e5 + 5;

void solve()
{
    int n, m;
    cin >> n >> m;
    std::mt19937 rnd(time(0));
    std::vector<ll> w(n + 1);
    ll sum = 0;
    for(int i = 1; i <= n; i++)
    {
        w[i] = rnd();
        sum += w[i];
    }
    std::vector<ll> r(n + 1), g(n + 1);
    ll tot = 0;
    for(int i = 1; i <= m; i++)
    {
        int u, v;
        cin >> u >> v;
        r[v] += w[u];
        tot += w[u];
    }
    for(int i = 1; i <= n; i++)g[i] = r[i];
    int q;
    cin >> q;
    while(q--)
    {
        int op, u, v;
        cin >> op;
        if(op == 1)
        {
            cin >> u >> v;
            r[v] -= w[u];
            tot -= w[u];
        }
        else if(op == 2)
        {
            cin >> u;
            tot -= r[u];
            r[u] = 0;
        }
        else if(op == 3)
        {
            cin >> u >> v;
            r[v] += w[u];
            tot += w[u];
        }
        else
        {
            cin >> u;
            tot += g[u] - r[u];
            r[u] = g[u];
        }
        if(tot == sum)cout << "YES\n";
        else cout << "NO\n";
    }
}

int main()
{
    // freopen("data.in", "r", stdin);
    // freopen("data.out", "w", stdout);
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);

    solve();
}
/*


*/

标签:cnt,星战,int,cin,P8819,随机化,op,else,out
From: https://www.cnblogs.com/pipipipipi43/p/18097034

相关文章

  • CF1514D-区间(绝对)众数-莫队、随机化、可持久化线段树
    link:https://codeforces.com/contest/1514/problem/D很久以前小号打的场了,当时D题写的莫队,现在重新来看看。题意:给一个序列\([a_1,\dots,a_n]\),有q次询问,每次问:把\([a_l,\dots,a_r]\)划分最少几个不相交子序列,才能使得每个子序列是beautiful的。称一个序列\(a_1,\dots,a_x\)......
  • 随机化算法
    1随机化算法简介随机化算法,是一种十分玄学的做法。百度百科对其的定义是:随机化算法(randomizedalgorithm),是这样一种算法,在算法中使用了随机函数,且随机函数的返回值直接或者间接的影响了算法的执行流程或执行结果。就是将算法的某一步或某几步置于运气的控制之下,即该算法在运......
  • 随机化小结
    交互中的随机暂时还没怎么做,等以后来总结。我个人是比较认同OI-wiki对随机化技术的分类的,但是对于具体技术,这里不遵循OI-wiki的分类。1随机限制命中元素经典应用有:3-SAT(通过随机添加限制,然后弱化到2-SAT解决2借助期望/概率经典应用有:1、随机游走的最大距离期望是根号......
  • SV 随机化(Randomization)
    CoverageDriverVerification可约束的随机化验证,用于测试的值可以再一定范围内进行随机,具体的范围可以进行约束,比如可以跑100次,然后查看覆盖率,可以通过覆盖率进行度量验证的进度内容随机化的变量往往需要添加一定的约束,通过添加约束让值在一定的范围内进行随机随......
  • 【学习笔记】随机化算法
    例题P7831[COCI2009-2010#3]PATULJCI题解首先对每个颜色开一个vector<int>保存其位置,随后对于一段区间\([l,r]\)和一个颜色\(c\),可以很快速的求出\([l,r]\)内\(c\)出现的次数。然后进行随机化,每次随机一个元素并查看他的出现次数。若随机\(t\)次,那么随机不到的概率是\(\frac......
  • 随机化贪心
    随机化什么是随机化算法?随机化做法,就是基于当前算法而言,通过正确算法求解会TLE或者MLE,但是出于骗分的目的,我对可能答案中的一些序列或者值进行查找,在我随机瞎找的这些值中去找正确答案,最后,所得出的答案具有极大可能性为正确答案,甚至于百分之一百。如果题目要求最优解,但难以......
  • SQLSmith: Databend 如何利用随机化测试检测 Bug
    作者:白珅Databend 研发工程师https://github.com/b41sh为什么需要SQLSmith?在数据库系统的开发和维护过程中,测试扮演着至关重要的角色。它不仅可以验证功能的正确性,还可以发现潜在的问题,确保数据库在每个变更和迭代后保持性能和稳定性。Databend的CI已经支持了多种类......
  • 转载:孟德尔随机化(Mendelian Randomization) 统计功效(power)和样本量计算
    链接:>https://mp.weixin.qq.com/s?__biz=Mzg2MDA2MDQzMQ==&mid=2247484734&idx=1&sn=6c4a5ba21bad0058ead4f0e8d9399c72&chksm=ce2d6b5ef95ae248ae7566d87d8aa4a373ccc33082a10e37773d89a137ac4d350e591844a0bd&scene=21#wechat_redirect......
  • 将vcf文件转成孟德尔随机化分析格式
    以https://gwas.mrcieu.ac.uk/datasets/ukb-b-7330/为例:原始文件形如:转换代码library(vcfR)getwd()a_data=read.vcfR('../ukb-b-7330.vcf.gz')str(a_data)head(a_data$meta,12)head(a_data@fix)head(a_data@gt)fix=as.data.frame(a_data@fix[,(1:5)])gt=as......
  • 下载微生物数据(孟德尔随机化)
    登录https://mibiogen.gcc.rug.nl/menu/main/home选择TopHits暴露因素选择条件0到1e-5或者5e-8作为结局数据选择条件5e-5到1根据菌群纲目ID进行分类,可以选择MendelR包里面的函数进行切割并自动化SNP模版split_mibiogen_file('刚才下载的文件.csv')libraray(Men......