首页 > 其他分享 >CSP-S 星战题解

CSP-S 星战题解

时间:2022-11-08 10:33:23浏览次数:67  
标签:tmp const cur 星战 题解 ll 出度 Pair CSP

更好的体验
首先可以观察出一个性质,只要每个点的出度都是 1,那么就一定会满足“每个点都能进入一个环”的性质,也就是说只要每个点出度为 1,那么该情况就是合法的。然后考虑怎么动态维护每个点的出度。

这里我们使用一个哈希,用一个值记录当前每个点的出度大小为多少,当这个值和“每个点出度为 1”这个状态的值一样的时候就是合法的值了。设出度为 \(ou\) 数组,定义哈希函数 $cur=\sum_{i=1}^n p^i \cdot ou_i $ ,那么当一条边 \(e_{i,j}\) 被毁,我们就给 \(cur\) 减去 \(p^i\) ,同理,当 \(e_{i,j}\) 被重建就给 \(cur\) 加上 \(p^i\) ,对于全体摧毁和全体重建,我们记录一个数组 \(pas_j\) 表示每一条以 \(j\) 为终点的边被摧毁时,对 \(cur\) 减值的总和,即 \(pas_j=\sum p^i\) ,其中边 \(e_{i,j}\) 被摧毁。再记录一个数组 \(in_j\) 表示一开始的时候每条以 \(j\) 为终点的边对 \(cur\) 的贡献的总和,即 \(in_j=\sum p^i\) 其中边 \(e_{i,j}\) 存在。那么集体摧毁的时候 \(cur\) 就应当减去 \(in_j-pas_j\) ,集体修复同理。具体可以参考代码,代码中为了求稳使用了双哈希。

另:由于本蒟蒻恶臭习惯,喜欢把出边和入边反过来写,所以代码里面 \(in\) 和 \(ou\) 含义交换。

#include<iostream>
#include<cstdio>
#include<cstring>
typedef long long ll;
using namespace std;
const ll N=6e5,p0=23333,mod1=998244353,mod2=1e9+7;
ll n,m,in[N],qu;

struct Pair{
	ll x,y;
	Pair operator *(const ll&tmp )const{
		Pair c;
		c.x=x*tmp%mod1,c.y=y*tmp%mod2;
		return c;
	}
	Pair operator +(const Pair&tmp )const{
		Pair c;
		c.x=(x+tmp.x)%mod1,c.y=(y+tmp.y)%mod2;
		return c;
	}
	Pair operator -(const Pair&tmp )const{
		Pair c;
		c.x=(x-tmp.x+mod1)%mod1,c.y=(y-tmp.y+mod2)%mod2;
		return c;
	}
	void clear(){x=0,y=0;}
}p[N],sam,cur,pas[N],ou[N];

int main(){
	cin>>n>>m;
	p[0].x=p[0].y=1;
	for(ll i=1;i<=n;i++)p[i]=p[i-1]*p0;
	for(ll i=1;i<=m;i++){
		ll a1,a2;
		scanf("%lld%lld",&a1,&a2);
		in[a1]++,ou[a2]=ou[a2]+p[a1];
	}
	for(ll i=1;i<=n;i++)sam=sam+p[i];
	for(ll i=1;i<=n;i++)
		cur=cur+(Pair){p[i].x*in[i]%mod1,p[i].y*in[i]%mod2};
	cin>>qu;
	for(ll i=1;i<=qu;i++){
		ll a1,a2,a3;
		scanf("%lld",&a1);
		if(a1==1){
			scanf("%lld%lld",&a2,&a3);
			cur=cur-p[a2];
			pas[a3]=pas[a3]+p[a2];
		}
		if(a1==2){
			scanf("%lld",&a2);
			cur=cur-ou[a2];
			cur=cur+pas[a2];
			pas[a2]=ou[a2];
		}
		if(a1==3){
			scanf("%lld%lld",&a2,&a3);
			cur=cur+p[a2];                                                                                                                       
			pas[a3]=pas[a3]-p[a2];
		}
		if(a1==4){
			scanf("%lld",&a2);
			cur=cur+pas[a2];
			pas[a2].clear();
		}
		if(cur.x==sam.x&&cur.y==sam.y)printf("YES\n");
		else printf("NO\n");
	}
}

标签:tmp,const,cur,星战,题解,ll,出度,Pair,CSP
From: https://www.cnblogs.com/caijiLYC/p/16868795.html

相关文章

  • AHOI2022山河重整 题解
    首先容易得到\(O(n^2)\)的解法,容易观察得出任意时刻范围都应是\([1,\sum]\)否则直接寄了。考察\(i\)使得\([1,i]\)都能凑出但\(i+1\)不行。则有\(\sum\limits_......
  • Long数据类型序列化Json后传递给前端,产生的精度丢失的问题解决
    问题产生的原因Long类型的数据,如果我们在后端将结果序列化为json,直接传给前端的话,在Long长度大于17位时会出现精度丢失的问题。java中的long能表示的范围比js中number大,......
  • 洛谷--【P1618】三连击升级版题解 排列枚举+循环枚举+stl
    题目描述将 1,2,…,91,2,…,9 共 99 个数分成三组,分别组成三个三位数,且使这三个三位数的比例是 A:B:C,试求出所有满足条件的三个三位数,若无解,输出 No!!!。输入格式......
  • CSP-S2022 游记
    成绩还没有出来,105分有点慌,只希望能够过线。DAY1不敢相信,这次CSP-S在本校(本人在九中光华集训)!!!下午考试,上午就直接在寝室里面睡大觉,睡到了早上10点左右,感觉精力很充沛。上......
  • 【游记】2022CSP-S游记?游寄!
    ......
  • 【题解】CSP-J2022
    CSP-J2022题解/Limie T1.乘方 简要题意:给定a,b,求a^b(a^b表示a的b次方)是否大于10^9,大于输出-1,小于等于输出a^b。分析:此题直接枚举1~b会超时,故考虑用位数判断大小,a^b......
  • BUUCTF [ACTF新生赛2020]SoulLike题解(非爆破)
    查壳发现无壳。   IDA检查main函数显然先检查了输入是否以actf{开头进入sub_83A无法进入 点不进去是因为IDA限制了解析函数的长度,可以修改IDA下cfg......
  • git 问题解决
    1.fatal:theremoteendhungupunexpectedlygitconfig--globalhttp.postBuffer104857600其他方案:gitconfig--globalpack.windowMemory100mgitconfig-......
  • 游记 CSP2022-J2/S2
    postedon2022-10-2822:41:08|under日志|sourceGD已经有代码了!游记写在代码里,搬过来吧。2022.10.29。GD-J00015/GD-S00013。FS石门中学。震惊:两个编号如此......
  • 【题解】codeforces 1746B Rebellion
    题意:给定一个只包含0和1的数组a,可以对a进行以下操作:选定两个下标不同的元素ai和aj,将ai加到aj上,再从数组中删除ai。问最少操作多少次,可以让数组a变成单调非下降子序列(即ai......