题目链接
题目大意
给你n个点,m次操作\(2\leq n \leq 2e5, 1\leq m \leq 2e5\)
操作分为三种
1:给u到v建立一条字符为ch的单向边
2:删除u到v的单向边
3:查询是否有k个点满足
\(v_1\rightarrow v_2 \rightarrow_.........v_k\)
\(v_k\rightarrow v_{k-1} \rightarrow_.........v_1\)
点可以重复
这两条路径上边的字符连接构成的字符串相等
题目思路
其实很简单qwq
首先要明确如果有满足答案的,那么在这条路径如果出现\(u\rightarrow v\)那么显然v到u也有一条单向边
k分奇偶讨论
若k为奇数,则可以直接\(u,v,u,v,u......u\)构造
若k为偶数,则显然\(ch[v_{mid}][v_{mid+1}]=ch[v_{mid+1}][v_{mid}]\)
那么可以直接\(v_{mid}\)和\(v_{mid+1}\)交叉构造
所以只需要维护两个值
一:是否存在两个点之间两两有边
二:是否存在两个点之间两两有边,且两边字符相等
代码
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
typedef long long ll;
typedef pair<double,int> pdi;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=2e5+5,mod=1e7;
int n,m;
int cnt1,cnt2;
unordered_map<int,int> mp[maxn];
int main(){
scanf("%d%d",&n,&m);
for(int i=1,u,v,k;i<=m;i++){
char opt,ch;
scanf(" %c",&opt);
if(opt=='+'){
scanf("%d %d %c",&u,&v,&ch);
mp[u][v]=ch;
if(mp[v][u]!=0){
cnt1++;
if(mp[v][u]==mp[u][v]){
cnt2++;
}
}
}else if(opt=='-'){
scanf("%d %d",&u,&v);
if(mp[v][u]!=0){
cnt1--;
if(mp[v][u]==mp[u][v]){
cnt2--;
}
}
mp[u][v]=0;
}else if(opt=='?'){
scanf("%d",&k);
bool flag;
if(k%2){
if(cnt1!=0){
flag=1;
}else{
flag=0;
}
}else{
if(cnt2!=0){
flag=1;
}else{
flag=0;
}
}
printf(flag?"YES\n":"NO\n");
}
}
return 0;
}