原题:

题目描述

   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个回答。如果所有回答都没问题,你就输出 所有回答的个数。


很明显,这道题是并查集(不要问我怎么看出来的)。

由于数据太大,需要离散化。

所谓离散化,就是把较大的一组数进行排序,然后对他们根据大小重新赋值,当数的大小不对数据本身有影响,只有大小对其有影响时,可以使用离散化。

离散化的标准姿势见 点这里

然而蒟蒻并不会标准姿势,说说自己的方法:

以本题为例,把所有的数据都存在nd结构体中

void init()
{
for(int i = ;i<=m;i++)
{
int x,y;
scanf("%d%d%s",&x,&y,c);
nd[i].p = x;//数组开三倍,p表示临时变量。一倍存左端点。
nd[i+m].p = y;//二倍存右端点。
nd[i].num = i;//每一倍都要给他们打上编号,一会排序时后会乱。
nd[i+m].num = i;if(c[]=='e')
{
nd[i+m+m].odd = ;//三倍存奇偶
}else
{
nd[i+m+m].odd = ;
}
}
}

读进来之后进行离散化。

void discretization()
{
for(int i = ;i<=*m;i++)
{
if(nd[nd[i].num].l==-)
{
nd[nd[i].num].l = cnt-;
}else
{
nd[nd[i].num].r = cnt;
}
if(nd[i+].p!=nd[i].p)
{
cnt++; //去重,不一样的时候再+1
}
}
for(int i = ;i<=m;i++)
{
nd[i].odd = nd[i+m+m].odd;从三倍搬回原数组
}
}

这样就离散完了。

接下来就是带权并查集的操作。

在合并和路径压缩的时候处理。

思路就是将一个区间右面的点认左面的点为父亲,两端区间合并的时候,根据奇偶性判断,0表示偶数,1表示奇数(有点懒,具体0或1见代码)。

int find(int x)
{
if(f[x]==x)
{
return f[x];
}
int fx = find(f[x]);
g[x] = (g[f[x]]+g[x])%;
return f[x] = fx;
}

最后上总代码:

#include<cstdio>
#include<algorithm>
#include<cmath>
#define ll long long
#define N 105550
using namespace std;
char c[];
ll n;
int m;
int cnt = ;
struct node
{
int l;
int r;
int num;
int odd;
int p;
}nd[N+N+N];
int f[N];
int g[N];
int cmp(node a,node b)
{
return a.p < b.p;
}
void init()
{
for(int i = ;i<=m;i++)
{
int x,y;
scanf("%d%d%s",&x,&y,c);
nd[i].p = x;
nd[i+m].p = y;
nd[i].num = i;
nd[i+m].num = i;
nd[i].l = -;
nd[i+m].l = -;
if(c[]=='e')
{
nd[i+m+m].odd = ;
}else
{
nd[i+m+m].odd = ;
}
}
}
void discretization()
{
for(int i = ;i<=*m;i++)
{
if(nd[nd[i].num].l==-)
{
nd[nd[i].num].l = cnt-;
}else
{
nd[nd[i].num].r = cnt;
}
if(nd[i+].p!=nd[i].p)
{
cnt++;
}
}
for(int i = ;i<=m;i++)
{
nd[i].odd = nd[i+m+m].odd;
}
}
int find(int x)
{
if(f[x]==x)
{
return f[x];
}
int fx = find(f[x]);
g[x] = (g[f[x]]+g[x])%;
return f[x] = fx;
}
int ans;
bool flag;
void uion(int x,int y,int i)
{
int fx = find(x);
int fy = find(y);
if(fx==fy)
{
if((nd[i].odd==&&g[x]==g[y])||(nd[i].odd==&&g[x]!=g[y]))
{
ans = i-;
flag = ;
return ;
}
find(y);
find(x);
}else
{
f[fy] = fx;
g[fy] = (g[x]+g[y]+nd[i].odd)%;
find(x);
find(y);
}
}
void solve()
{
for(int i = ;i<=cnt;i++)
{
f[i] = i;
}
for(int i = ;i<=m;i++)
{
int l = nd[i].l;
int r = nd[i].r;
uion(l,r,i);
if(flag==)
{
printf("%d\n",ans);
return ;
}
}
printf("%d\n",m);
}
int main()
{
scanf("%lld",&n);
scanf("%d",&m);
init();
sort(nd+,nd++m+m,cmp);
discretization();
solve();
return ;
}

小胖的奇偶(Viojs1112)题解的更多相关文章

  1. [vijos P1112] 小胖的奇偶

    第一次看到这题怎么也不会想到是并查集题目…星期五第一次看到这题,到今天做出来,实在是废了好多功夫.看了很多人的解题都有same和diff数组,我也写了,后来发现不对啊两个数组的话find函数怎么写呢? ...

  2. Vijos 小胖的奇偶

    第一遍做 #include<iostream> #include<cstdlib> #include<cstdio> #include<cstring> ...

  3. 【带权并查集】【离散化】vijos P1112 小胖的奇偶

    每个区间拆成r和l-1两个端点,若之内有偶数个1,则这两个端点对应的前缀的奇偶性必须相同,否则必须相反. 于是可以用带权并查集维护,每个结点储存其与其父节点的奇偶性是否相同,并且在路径压缩以及Unio ...

  4. VijosP1112:小胖的奇偶

    描述 huyichen和xuzhenyi在玩一个游戏:他写一个由0和1组成的序列. huyichen选其中的一段(比如第3位到第5位),问他这段里面有奇数个1还是偶数个1.xuzhenyi回答你的问题 ...

  5. BZOJ 3714: [PA2014]Kuglarz

    Description 魔术师的桌子上有n个杯子排成一行,编号为1,2,-,n,其中某些杯子底下藏有一个小球,如果你准确地猜出是哪些杯子,你就可以获得奖品.花费c_ij元,魔术师就会告诉你杯子i,i+ ...

  6. 【并查集模板】 【洛谷P2978】 【USACO10JAN】下午茶时间

    P2978 [USACO10JAN]下午茶时间Tea Time 题目描述 N (1 <= N <= 1000) cows, conveniently numbered 1..N all a ...

  7. Tempter of the Bone(dfs+奇偶剪枝)题解

    Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

  8. 力扣(LeetCode)按奇偶排序数组II 个人题解

    给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数. 对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数:当 A[i] 为偶数时, i 也是偶数. 你可以返回任何满足上述条件的数组 ...

  9. 小胖守皇宫(VIJOS P1144 )题解

    题目描述 huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫. 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状:某些宫殿间可以互相望见.大内保卫森严,三步一岗,五步一哨,每 ...

随机推荐

  1. docker 安装tomcat容器和mysql容器

    1. docker pull mysql:5.6 2.docker run -p 3306:3306 --name mysql -v /data/mysql/conf:/etc/mysql/conf. ...

  2. Web api 右连接

    这是原来的代码,两个表的连接的方式是inner join ,查不出我要的全部数据. 后来把代码稍稍改一下,就是left join  join into 到一个临时对象里,相当于再select from ...

  3. RabbitMQ学习之Publish/Subscribe(3)

    上一个教程中,我们创建了一个work queue. 其中的每个task都会被精确的传送到一个worker. 这节,我们将会讲把一个message传送到多个consumers. 这种模式叫做publis ...

  4. Mybatis源码解析(四) —— SqlSession是如何实现数据库操作的?

    Mybatis源码解析(四) -- SqlSession是如何实现数据库操作的?   如果拿一次数据库请求操作做比喻,那么前面3篇文章就是在做请求准备,真正执行操作的是本篇文章要讲述的内容.正如标题一 ...

  5. Java自学-数字与字符串 数学方法

    Java Math类常用方法 java.lang.Math提供了一些常用的数学运算方法,并且都是以静态方法的形式存在 步骤 1 : 四舍五入, 随机数,开方,次方,π,自然常数 package dig ...

  6. CSRF漏洞的挖掘与利用

    0x01 CSRF的攻击原理 CSRF 百度上的意思是跨站请求伪造,其实最简单的理解我们可以这么讲,假如一个微博关注用户的一个功能,存在CSRF漏洞,那么此时黑客只需要伪造一个页面让受害者间接或者直接 ...

  7. DataPipeline丨「自定义」数据源,解决复杂请求逻辑外部数据获取难题

    A公司专注为各种规模和复杂程度的金融投资机构提供一体化投资管理系统,系统主要由投资组合管理.交易执行管理.实时监控管理.风险管理等功能模块构成.随着企业管理产品数量的不断增多,大量数据分散在各券商系统 ...

  8. Windows - CMD窗口UTF8编码乱码问题的解决!

    问题描述    用MS-DOC打开 UTF-8 的文件时, 显示乱码问题根源    CMD默认是Windows系统默认编码(GBK),    用GBK格式来解码UTF-8的文件当然会出现乱码.解决方案 ...

  9. Solr新特性【4.x,5.x,6.x,7.x】

    一.Solr4.x新特性 1.近实时搜索 Solr的近实时搜索[Near Real-Time,NRT]功能实现了文档添加到搜索的快速进行,以应对搜索快速变化的数据. 2.原子更新与乐观并发 原子更新功 ...

  10. Mysql连接数过多、Mysql连接错误过多的问题处理

    在使用Mysql的过程中,你总是会遇到这样那样的问题,每次去网上查找也相对比较麻烦,所以在此整理一下(以linux ubantu16 系统为例). ========================== ...