E. AZ Graph 题解(思维)

题目链接

题目大意

给你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;
}

不摆烂了,写题
原文地址:https://www.cnblogs.com/hunxuewangzi/p/14484680.html