p4899 [IOI2018] werewolf 狼人

分析

我用的主席树维护qwq

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
struct node {
    int le,ri,sum;
};
node d[400005*35];
int n,m,q,val[400005],rt[400005],cnt;
vector<int>v[400005];
struct Tree {
    int kk,dfn[400005],fin[400005],fa[400005],pa[400005][21],T;
    vector<int>vv[400005];
    inline int sf(int x){return fa[x]==x?x:fa[x]=sf(fa[x]);}
    inline void dfs(int x){
      dfn[x]=++T;
      for(int i=1;i<20;i++)pa[x][i]=pa[pa[x][i-1]][i-1];
      for(int i=0;i<vv[x].size();i++)dfs(vv[x][i]);
      fin[x]=T;
    }
    inline void work(){
      int i,j,k;
      for(i=1;i<=n;i++)fa[i]=i;
      if(kk){
          for(i=n;i;i--)
            for(j=0;j<v[i].size();j++)
              if(i<v[i][j]){
                k=sf(v[i][j]);
                if(k==i)continue;
                vv[i].push_back(k);
                fa[k]=pa[k][0]=i;
            }
        dfs(1);
      }else {
          for(i=1;i<=n;i++)
            for(j=0;j<v[i].size();j++)
              if(i>v[i][j]){
                k=sf(v[i][j]);
                if(k==i)continue;
                vv[i].push_back(k);
                fa[k]=pa[k][0]=i;
            }
        dfs(n);
      }
    }
    inline int go(int x,int len){
      int i,j,k;
      for(i=19;i>=0;i--)
        if(pa[x][i]&&((kk&&pa[x][i]>=len)||(!kk&&pa[x][i]<=len)))
          x=pa[x][i];
      return x;
    }
};
Tree A,B;
inline void update(int &x,int y,int le,int ri,int k){
    d[++cnt]=d[y];
    d[cnt].sum++;
    x=cnt;
    if(le==ri)return;
    int mid=(le+ri)>>1;
    if(mid>=k)update(d[x].le,d[y].le,le,mid,k);
      else update(d[x].ri,d[y].ri,mid+1,ri,k);
}
inline int que(int a,int b,int le,int ri,int x,int y){
    if(le>=x&&ri<=y)return d[a].sum-d[b].sum;
    int mid=(le+ri)>>1,Ans=0;
    if(mid>=x)Ans+=que(d[a].le,d[b].le,le,mid,x,y);
    if(mid<y)Ans+=que(d[a].ri,d[b].ri,mid+1,ri,x,y);
    return Ans;
}
int main(){
    int i,j,k,x,y;
    scanf("%d%d%d",&n,&m,&q);
    for(i=1;i<=m;i++){
      scanf("%d%d",&x,&y);
      x++,y++;
      v[x].push_back(y);
      v[y].push_back(x);
    }
    A.kk=1;A.work();B.work();
    for(i=1;i<=n;i++)val[A.dfn[i]]=B.dfn[i];
    for(i=1;i<=n;i++)update(rt[i],rt[i-1],1,n,val[i]);
    for(i=1;i<=q;i++){
      int s,t,le,ri;
      scanf("%d%d%d%d",&s,&t,&le,&ri);
      s++,t++,le++,ri++;
      s=A.go(s,le),t=B.go(t,ri);
      if(que(rt[A.fin[s]],rt[A.dfn[s]-1],1,n,B.dfn[t],B.fin[t]))puts("1");
        else puts("0");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/yzxverygood/p/11547277.html

时间: 2024-11-06 09:27:26

p4899 [IOI2018] werewolf 狼人的相关文章

[IOI2018] werewolf 狼人 kruskal重构树,主席树

[IOI2018] werewolf 狼人 LG传送门 kruskal重构树好题. 日常安利博客文章 这题需要搞两棵重构树出来,这两棵重构树和我们平时见过的重构树有点不同(据说叫做点权重构树?),根据经过我们简化的建树方法,这两棵树不再是二叉树,但是仍具有kruskal重构树的优秀性质,建议结合后面的描述理解. 看这题需要首先我们从\(S\)走到\(T\)转化为分别从\(S\)和\(T\)出发寻找能共同到达的点,需要快速求出从某个点出发经过点权不大(小)于\(r\)(\(l\))的点,考虑kru

[IOI2018] werewolf 狼人

[IOI2018] werewolf 狼人 IOI2018题解 代码: #include<bits/stdc++.h> #define reg register int #define il inline #define numb (ch^'0') using namespace std; typedef long long ll; il void rd(int &x){ char ch;x=0;bool fl=false; while(!isdigit(ch=getchar()))(

[IOI2018]werewolf狼人——kruskal重构树+可持久化线段树

题目链接: IOI2018werewolf 题目中编号都是从0开始,太不舒服了,我们按编号从1开始讲QAQ. 题目大意就是询问每次从一个点开始走只能走编号在[l,n]中的点,在任意点变成狼,之后只能走[0,r]中的点,是否能到达另一个点. 后一部分其实就是找有哪些点只走[0,r]中的点能到达终点,那么反过来看,就是终点只走[0,r]中的点能到达哪些点. 那么只要起点能到达的点和终点能到达的点中有交集就有解. 因为起点只能走一些编号较大的点,那么我们求出原图的最大生成树,建出kruskal重构树,

HDU 6370 Werewolf 【并查集】

任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6370 Werewolf Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 2680    Accepted Submission(s): 806 Problem Description "The Werewolves" is a p

1148 Werewolf - Simple Version (20 分)

Werewolf(狼人杀) is a game in which the players are partitioned into two parties: the werewolves and the human beings. Suppose that in a game, player #1 said: "Player #2 is a werewolf."; player #2 said: "Player #3 is a human."; player #3

PAT_A1148#Werewolf - Simple Version

Source: PAT A1148 Werewolf - Simple Version (20 分) Description: Werewolf(狼人杀) is a game in which the players are partitioned into two parties: the werewolves and the human beings. Suppose that in a game, player #1 said: "Player #2 is a werewolf."

1148 Werewolf - Simple Version (20 分)

1148 Werewolf - Simple Version (20 分) Werewolf(狼人杀) is a game in which the players are partitioned into two parties: the werewolves and the human beings. Suppose that in a game, player #1 said: "Player #2 is a werewolf."; player #2 said: "P

URAL 1242 Werewolf(DFS)

Werewolf Time limit: 1.0 secondMemory limit: 64 MB Knife. Moonlit night. Rotten stump with a short black-handled knife in it. Those who know will understand. Disaster in the village. Werewolf. There are no so many residents in the village. Many of th

狼人杀 — 水平阶级的划分

作者:来自公众号 狼人杀搞事吧 的洋洋 大家玩的时候可能经常会在局外听到有人说"某某是四阶大神-". 这次洋洋给大家介绍一下狼人杀水平的判定标准,也就是所谓的"阶级".等你了解完这些,就可以像老司机一样出去各种装逼各种吹了. 水平阶级划分介绍 0阶玩家 刚刚接触狼人杀游戏,只对角色功能有一定了解,发言比较划水或者直接过,玩神直接爆身份,常常作为闭眼玩家不知道该讲什么,当狼时比较紧张,发言漏洞比较大,基本没有悍跳预言家成功经历.    1阶玩家 了解狼人杀基本套路和逻