www 被大佬|

wscqwq

园龄:2年粉丝:2关注:3

星战

https://www.luogu.com.cn/problem/P8819

https://www.acwing.com/problem/content/description/4737/

  • 为了使虫洞穿梭的过程连续,尽量减少战舰在据点切换虫洞时的质能损耗,当且仅当只有一个从该据点出发的虫洞可用时,这个据点可以实现连续穿梭
  • 如果我方所有据点都可以实现连续穿梭,那么每个点都可以一直走,也能满足我方所有据点都可以实现反击,所以只需要判断每个点的出度是否都是 1 即可。

我们把终点为据点 u 的所有虫洞归为据点 u 的虫洞。

敌人会摧毁某个虫洞,这会使它连接的两个据点无法再通过这个虫洞直接到达,但这样的打击无法摧毁它连接的两个据点。

B 型特种部队可以将某据点的所有损坏的虫洞修复。

  • t=2,接下来一个整数 u 表示敌人摧毁了据点 u。如果该据点的虫洞已全部被摧毁,那么这次袭击不会有任何效果。
  • t=4,接下来一个整数 u 表示我方修复了据点 u。如果该据点没有被摧毁的虫洞,那么这次修复不会有任何效果。

题目的暗示:记录每个点的出度,可以分别记录以点 u 为终点的虫洞的起始点有哪些点,用一个01数组记录,若有 iu 的边,则 su 的第 i 位=1。然后最后求 u=1nsu 是否恰好每一位都是1即可。

如果按照 n 位维护,遇到2、4操作,无论如何都是 O(n),最坏达到 O(nq),TLE。

由CCF的特性以及往年无解的分数可知,正确率高的算法也可以通过此题。

我们发现这个东西很像字符串哈希,将一个需要 O(n) 比较的str转换成num,只是需要支持相加操作。

其实每一位赋值不同的权值,发现 h(sx)+h(sy)=h(sx+sy),因为每一位是可以单独考虑的。

我们将 su 转换成了哈希值了。

每次只需要将涉及到的那个 su 先减去,遇到1、3更新一位,遇到2、4直接置空、恢复初始状态,然后加上新的值即可。

用 ull 可以自动取模。

复杂度 O(n+m+q)

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N=500010,P=13331;
int n,m,q;
ull p[N],ao,res,org[N],cur[N];
int main(){
    #ifndef ONLINE_JUDGE
    freopen("1.txt","r",stdin);
    #endif
    #ifdef ONLINE_JUDGE
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    #endif
    p[0]=1;
    cin>>n>>m;
    for(int i=1;i<=n;++i)p[i]=p[i-1]*P;
    for(int i=1;i<=m;++i){
    	int a,b;
    	cin>>a>>b;
    	org[b]+=p[a],cur[b]+=p[a];
	}
	for(int i=1;i<=n;++i)ao+=p[i],res+=cur[i];
	cin>>q;
	for(int i=1;i<=q;++i){
		int t,u,v=0;
		cin>>t>>u;
		if(t==1||t==3)cin>>v;
		res-=cur[u]+cur[v];
		if(t==1)cur[v]-=p[u];
		if(t==2)cur[u]=0;
		if(t==3)cur[v]+=p[u];
		if(t==4)cur[u]=org[u];
		res+=cur[u]+cur[v];
		cout<<(ao==res?"YES\n":"NO\n");
	}
    return 0;
}

这种做法的名字:和哈希

本文作者:wscqwq

本文链接:https://www.cnblogs.com/wscqwq/p/18298593

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   wscqwq  阅读(4)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起