EZOI+1

【问题描述】

“君不见Oxer 感染 AHdoc,愈发喜爱毒瘤题。

 “君不见多组数据卡常数,难写难调难对拍

“……”

 一首《将进酒》道出了Oxer 对于毒瘤题的热爱与执着。

现在,他开始对一些毒瘤题进行分类,开始时,每道毒瘤题都是各自一类,每次,他会选择两道毒瘤题,认为他们是类似的(我们也认为类似是可以传递的,即类似,类似,则类似),然后把他们写在自己的博客里,来准备即将到来的noi。 

有趣的是,Oxer 有时会否定自己的分类,所以,他会从以往的一篇博客中找出一篇,以此为基础来进行新的分类。 

可是,山东省西北部某个奇怪的学校里的一些别有用心的奇怪的人总希望能够按照Oxer 对于毒瘤题的分类来进行复习noi。 

他们写了一个程序,能够快速查询两道毒瘤题在 Oxer 的某一篇博客中的是否是一类。

Oxer 对于他们的程序很感兴趣,希望能把这个程序出成一道毒瘤题来放在未来的 noi 中。

那么,你帮忙写个标程(暴力也行)好吗。

注意:开始时,Oxer 的博客中已经有一篇博客,我们称其为第篇,在第0篇博客中,每道题都是两两不类似的。

【输入格式】从文件 noi.in 读入输入文件共m+1 行。

第一行包括两个整数n  m,n 表示题目数量,表示程序的指令数量。第二行到第m+1 行,第 i+1 行分为如下两种情况:

L k a b 表示将第k 篇博客(初始为第0 篇)中的a 和b 两道题是类似的,并将现在的分类情况保存到第篇博客中。(如果已经是类似的,那么忽略这次操作)

Q k a b 表示查询第k 篇博客(初始为第0 篇)中的a 和b 两道题是否是类似的,若是,则输出“Fangfang”;若不是,则输出“Yuanyuan”。

 

 

 

思路:可持久化并查集

大致上,离线建操作树,dfs每次进入到一个建立在其father上的操作合并,退出时操作撤销

合并时使用启发式合并(就是说size小的连到大的上)

附代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cmath>
  5 #define N 1100000
  6 using namespace std;
  7 int n,m,cntop,cntqu,sz1,sz2;
  8 struct fx{
  9     int to,a,b,next;
 10 }op[N];
 11 struct gx{
 12     int ans,id,a,b,next;
 13 }qu[N];
 14 int headop[N],headqu[N];
 15 int size[N],father[N];
 16 char ch[5];
 17 bool cmp(gx p,gx q){
 18     return (p.id<q.id);
 19 }
 20 int find(int x){
 21     if (father[x]!=x) father[x]=find(father[x]);
 22     return father[x];
 23 }
 24 void addop(int a,int b,int x,int y){
 25     cntop++;
 26     op[cntop].next=headop[a];
 27     headop[a]=cntop;
 28     op[cntop].to=b;
 29     op[cntop].a=x;
 30     op[cntop].b=y;
 31 }
 32 void addqu(int a,int id,int x,int y){
 33     cntqu++;
 34     qu[cntqu].next=headqu[a];
 35     headqu[a]=cntqu;
 36     qu[cntqu].a=x;
 37     qu[cntqu].b=y;
 38     qu[cntqu].id=id;
 39 }
 40 void dfs(int x){
 41     for (int e=headqu[x];e;e=qu[e].next){
 42         int a=find(qu[e].a);
 43         int b=find(qu[e].b);
 44         if (a!=b) qu[e].ans=0;
 45         else qu[e].ans=1;
 46     }
 47     for (int e=headop[x];e;e=op[e].next){
 48         int mark=0; 
 49         int r1=find(op[e].a);
 50         int r2=find(op[e].b);
 51         if (r1!=r2){
 52             if (size[r1]>size[r2])
 53                 mark=1;
 54             else 
 55                 mark=0;
 56             if (mark){
 57                 father[r2]=father[r1];
 58                 size[r1]+=size[r2];
 59             }
 60             else {
 61                 father[r1]=father[r2];
 62                 size[r2]+=size[r1];
 63             }
 64             dfs(op[e].to);
 65             if (mark){
 66                 father[r2]=r2;
 67                 size[r1]-=size[r2];
 68             }
 69             else {
 70                 father[r1]=r1;
 71                 size[r2]-=size[r1];
 72             }
 73         }
 74         else 
 75             dfs(op[e].to);
 76     }
 77 }
 78 int main(){
 79     freopen("noi.in","r",stdin);
 80     freopen("noi.out","w",stdout);
 81     cntqu=cntop=0;
 82     scanf("%d %d",&n,&m);
 83     for (int i=1;i<=n;i++){
 84         father[i]=i;
 85         size[i]=1;
 86     }
 87     for (int i=1;i<=m;i++){
 88         scanf("%s",ch);
 89         int tmp,x,y;
 90         scanf("%d %d %d",&tmp,&x,&y);
 91         if (ch[0]=='L')
 92             addop(tmp,i,x,y);
 93         if (ch[0]=='Q') 
 94             addqu(tmp,i,x,y);
 95     }
 96     dfs(0);
 97     sort(qu+1,qu+cntqu+1,cmp);
 98     for (int e=1;e<=cntqu;e++)
 99         if (qu[e].ans==1)
100             printf("Fangfang\n");
101         else 
102             printf("Yuanyuan\n");
103     return 0;
104 }
STD

 

posted on 2016-10-20 21:33  Absolutezero  阅读(273)  评论(0编辑  收藏  举报