首页 > 其他分享 >P8819 [CSP-S 2022] 星战

P8819 [CSP-S 2022] 星战

时间:2022-11-23 20:48:40浏览次数:40  
标签:ch Hash 星战 read sum CSP while 2022 ll

[CSP-S 2022] 星战

这么长时间过去都快不会写题解了。

嗯……不过还是稍微记一下会比较好。

题意看完之后就是让我们去判断整张图是否是一个内向基环树森林。

然后这个事情判度数肯定是好的,每个点的出度都为 \(1\) 即可。

但是这个维护很奇葩,想不出来什么维护方法。

然后被 Sum Hash 震撼到了。

干脆想办法看看是不是每个点都出现了一次。

简单来说,首先给每个点一个随机的 Hash 值 \(h (x)\)。

然后,定义每个点的一个值 \(f(x)\),令 \(f(x) = \sum _ {(y,x) \in E}h (y)\)。

因为题目的修改操作挺特殊的(只针对出点是该点的边),因此每个 \(f(x)\) 和 \(\sum f(x)\) 都是可以在 \(O ( 1 )\) 的复杂度下维护的。

那么维护这个 \(\sum f(x)\) 的作用在什么地方?

如果我们想一想,当 \(\sum h(x) = \sum f(x)\) 的时候,最有可能的情况是什么?

凭直觉得到,最有可能是所有点出度为 \(1\) 的时候。

Hash 其实就是这么个很不讲道理的东西,很多时候就是直觉上正确就能用 Hash……

我们维护 \(f(x)\) 即可。

当然,为了减小出错的可能性,多做几组 Hash 是更好的。这里我就做了 \(32\) 组,但是准确性足够了。

另外喷一下这个官方造数据的(全输出否都能得 45pts……)。

总的时间复杂度是 \(O(n+m+kq)\) 的(其中 \(k\) 指 Hash 的组数)。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#define ll long long
using namespace std;
namespace Ehnaev{
  inline ll read() {
    ll ret=0,f=1;char ch=getchar();
    while(ch<48||ch>57) {if(ch==45) f=-f;ch=getchar();}
    while(ch>=48&&ch<=57) {ret=(ret<<3)+(ret<<1)+ch-48;ch=getchar();}
    return ret*f;
  }
  inline void write(ll x) {
    static char buf[22];static ll len=-1;
    if(x>=0) {do{buf[++len]=x%10+48;x/=10;}while(x);}
    else {putchar(45);do{buf[++len]=-(x%10)+48;x/=10;}while(x);}
    while(len>=0) putchar(buf[len--]);
  }
}using Ehnaev::read;using Ehnaev::write;

const ll N=5e5;

ll n,m,u,v,tot,q;
ll ver[N+5],nxt[N+5],head[N+5],a[35][N+5],f[35][N+5],bgn[35][N+5]
,ff[N+5],hsh[N+5];

inline void Add(ll u,ll v) {ver[++tot]=v;nxt[tot]=head[u];head[u]=tot;}

int main() {

  n=read();m=read();
  for(ll i=1;i<=m;i++) {u=read();v=read();Add(u,v);}

  srand(73939133);
  for(ll k=0;k<=31;k++) {
    for(ll i=1;i<=n;i++) {a[k][i]=rand();hsh[k]+=a[k][i];}
    for(ll i=1;i<=n;i++) {
      for(ll j=head[i];j;j=nxt[j]) {
        bgn[k][ver[j]]+=a[k][i];f[k][ver[j]]+=a[k][i];
      }
    }
    for(ll i=1;i<=n;i++) ff[k]+=f[k][i];
  }
  
  q=read();
  while(q--) {
    ll t=read();
    if(t==1) {
      u=read();v=read();
      for(ll k=0;k<=31;k++) {f[k][v]-=a[k][u];ff[k]-=a[k][u];}
    }
    if(t==2) {
      u=read();
      for(ll k=0;k<=31;k++) {ff[k]-=f[k][u];f[k][u]=0;}
    }
    if(t==3) {
      u=read();v=read();
      for(ll k=0;k<=31;k++) {f[k][v]+=a[k][u];ff[k]+=a[k][u];}
    }
    if(t==4) {
      u=read();
      for(ll k=0;k<=31;k++) {ff[k]+=bgn[k][u]-f[k][u];f[k][u]=bgn[k][u];}
    }
    ll flg=0;
    for(ll k=0;k<=31;k++) {
      if(ff[k]!=hsh[k]) {flg=1;break;}
    }
    if(flg) printf("NO\n");
    else printf("YES\n");
  }


  return 0;
}

标签:ch,Hash,星战,read,sum,CSP,while,2022,ll
From: https://www.cnblogs.com/Apolynth/p/16919714.html

相关文章

  • 【2022-11-23】爬虫从入门到入狱(一)
    一、爬虫介绍#爬虫介绍: 网络爬虫(webcrawler)又称为网络蜘蛛(webspider)或网络机器人(webrobot),另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或蠕虫,同时它也是“物联......
  • 2022.11.23
    一说到清朝的闭关锁国,大家都很痛心疾首、愤愤不平,觉得要是没有闭关锁国的话,可能中国依然是强国,也能避免后来的那些耻辱了。但有意思的是,现在还是有很多人闭关锁国,他们对......
  • @tranctional +@feighclient 注解的一些细节2022-11-23
    rollbackfall  有异常,则回滚  该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚, 指定单一异常类:@Transactional(ro......
  • 2022 云原生编程挑战赛圆满收官,见证冠军战队的诞生
    11月3日,天池大赛·第三届云原生编程挑战赛在杭州云栖大会圆满收官。三大赛道18大战队手历经3个月激烈的角逐,终于交上了满意的答卷,同时也捧回了属于他们的荣耀奖杯。......
  • kali linux 2022.1版本root密码重置
    1、按e进入修复模式2、在linux行尾输入rwsingleinit=/bin/bash3、Ctrl+x进入命令行界面4、使用passwd命令修改root密码,完成后重启5、使用root用户登录6、重置成功......
  • 2022 卡塔尔世界杯视频直播 All In One
    2022卡塔尔世界杯视频直播AllInOne抖音https://www.douyin.com/fifaworldcuphttps://www.douyin.com/search/CCTV164K视频refs©xgqfrms2012-2021w......
  • 周六900C++班级-2022-11-19 01背包
    背包问题关系图  问题描述若有N件物品和一个最多能装重量为W的背包,一个物品只有两个属性:重量和价值。第i件物品的重量是weight[i],得到的价值是value[i]。假......
  • 第三届数字四川创新大赛(2022)“天空卫士杯”数据安全赛道决赛暨颁奖典礼成功举行
    2022年11月17日,由四川省大数据中心、省委网信办、省发展改革委、经济和信息化厅和省科协联合主办,北京天空卫士网络安全技术有限公司协办的第三届数字四川创新大赛(2022)数据安......
  • hgame2022 复现
    enterthepwnland​pthread_create()函数:创建线程intpthread_create(pthread_t*thread,constpthread_attr_t*attr,void......
  • NOIP 2022 游记
    Day-2近日模拟赛状态:打模拟赛:AK了:这么傻逼的模拟赛不是谁都AK,有什么训练效果吗\(\to\)自闭没AK:挂分了:wdnmd怎么又挂分\(\to\)自闭没挂分:wdnmd怎么就......