LNSYOJ201小胖的奇偶并查集+离散化做题报告

Posted qin-wei-kai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LNSYOJ201小胖的奇偶并查集+离散化做题报告相关的知识,希望对你有一定的参考价值。

这道题是一个带权并查集

题目描述

   huyichen和xuzhenyi在玩一个游戏:他写一个由0和1组成的序列。 huyichen选其中的一段(比如第3位到第5位),问他这段里面有奇数个1 还是偶数个1。xuzhenyi回答你的问题,然后huyichen继续问。 xuzhenyi有可能在撒谎。huyichen要检查xuzhenyi的答案,指出在xuzhenyi的第几个回答一定有问题。 有问题的意思就是存在一个01序列满足这个回答前的所有回答,而且不存在序列 满足这个回答前的所有回答及这个回答。

 

输入格式

第1行一个整数,是这个01序列的长度1000000000)(≤1000000000) 第2行一个整数,是问题和答案的个数(5000)(≤5000)。 第3行开始是问题和答案, 每行先有两个整数,表示你询问的段的开始位置和结束位置。 然后是xuzhenyi的回答。odd表示有奇数个1,even表示有偶数个

输出格式

输出一行,一个数X,表示存在一个01序列满足第1到第X个回答, 但是不存在序列满足第1到第X+1个回答。如果所有回答都没问题,你就输出 所有回答的个数。

样例一

input

10
5
1 2 even
3 4 odd
5 6 even
1 6 even
7 10 odd

output

3

限制与约定

时间限制1s

空间限制256MB

思路还是比较好想的,0代表偶数个,1代表奇数个

本题关键是理解

l r even 等价于0-l-1与0-R的序列奇偶性相同。odd等价于奇偶性相反

合并方式和食物链,关押罪犯很像;

这道题有一个很重要的东西是离散化

网上的代码是

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=1e5+7;
 6 int t[N],a[N],n,m;
 7 int main()
 8 {
 9     cin>>n;
10     for(int i=1;i<=n;i++)
11         cin>>a[i],t[i]=a[i];
12     sort(t+1,t+n+1);
13     m=unique(t+1,t+n+1)-t-1;
14     for(int i=1;i<=n;i++)
15     a[i]=lower_bound(t+1,t+m+1,a[i])-t;
16     for(int i=1;i<=n;i++)cout<<a[i]<<" ";
17 }

这个一定要记住!!(unique是去重函数)

还有一种就是用结构体,也是我这道题用的,先记录一个数据的位置,排完序之后再将它是第几大赋回去;

针对具体情况还要进行改动,比如本题进行了题号的记录和排序,要灵活处理!

注意:

1.要用l-1来查询和修改,网上有读的时候就- -的,也可以

2.用结构体离散化,要注意相同数的处理(见35-41行)

3.最后记得要输出最后一个号码,我就是忘了,导致了好多个EOF

AC代码在此

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 struct node{
 5     int data,no,op,hs;
 6 }nd[5100*2];//0:l,1:r;
 7 int n,k,f[5100*2],val[5100*2];
 8 char opt[5100][51];
 9 int find(int x)
10 {
11     if(f[x]==x)return x;
12     int ff=find(f[x]);
13     val[x]=(val[x]+val[f[x]])%2;
14     return f[x]=ff;
15 }
16 bool cmp1(node a,node b)
17     {return a.data<b.data;}
18 bool cmp2(node a,node b)
19     {return a.no<b.no;}
20 int main()
21 {
22     scanf("%d%d",&n,&k);
23     for(int i=1;i<=k;i++)
24     {
25         scanf("%d",&nd[i].data);
26         nd[i].no=i;
27         nd[i].op=0;
28         nd[i].data;
29         scanf("%d",&nd[i+k].data);
30         nd[i+k].no=i;
31         nd[i+k].op=1;
32         scanf("%s",opt[i]);
33     }
34     sort(nd+1,nd+2*k+1,cmp1);
35     int tt=0;
36     for(int i=1;i<=2*k;i++)
37     {
38         if(nd[i].data==nd[i-1].data)nd[i].hs=tt;
39         else nd[i].hs=++tt;
40         f[tt]=tt;
41     }
42     sort(nd+1,nd+2*k+1,cmp2);
43     int cnt=0;
44     for(int i=1;i<=2*k;i+=2)
45     {
46         cnt++;
47         int l,r;
48         for(int j=i;j<=i+1;j++)
49         {
50             if(nd[j].op==1)r=nd[j].hs;
51             else l=nd[j].hs;
52         }
53         int fx=find(l-1),fy=find(r);
54         if(opt[cnt][0]==e)
55         {
56             if(fx!=fy)
57             {
58                 val[fy]=(val[l-1]+val[r])%2;
59                 f[fy]=fx;
60             }else
61             {
62                 if(val[l-1]!=val[r])
63                 {
64                     printf("%d",nd[i].no-1);
65                     return 0;
66                 }
67             }
68         }else if(opt[cnt][0]==o)
69         {
70             if(fx!=fy)
71             {
72                 val[fy]=(val[l-1]+val[r]+1)%2;
73                 f[fy]=fx;
74             }else
75             {
76                 if(val[l-1]==val[r])
77                 {
78                     printf("%d",nd[i].no-1);
79                     return 0;
80                 }
81             }
82         }
83     }
84     printf("%d",k);
85     return 0;
86 }

 

 

By 浅夜_MISAKI

 

以上是关于LNSYOJ201小胖的奇偶并查集+离散化做题报告的主要内容,如果未能解决你的问题,请参考以下文章

「带权并查集」奇偶游戏

Parity game——带权并查集

BZOJ 4195: [Noi2015]程序自动分析 [并查集 离散化 | 种类并查集WA]

poj 1733 Parity game(种类并查集)

POJ 1733 Parity game(种类并查集)

Codeforces Round #396 (Div. 2) D题Mahmoud and a Dictionary(并查集)解题报告