BZOJ 1594 [Usaco2008 Jan]猜数游戏(线段数)
1594: [Usaco2008 Jan]猜数游戏
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 626 Solved: 260
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
1 10 7
5 19 7
3 12 8
11 15 12
输入说明:
编号为1..10的草堆中,最小的那堆里有7捆草,编号为5..19的草堆中同样如此;编号为3..12的草堆中最小的堆里
是8捆草,11..15堆中的最小的堆里是12捆。
Sample Output
输出说明:
对于第3个问题“3 12”的回答“8”与前面两个回答冲突。因为每堆中草的捆数唯一,从前两个回答中我们能推断
出,编号为5..10的干草堆中最小的那堆里有7捆干草。很显然,第3个问题的回答与这个推断冲突。
题解
矛盾只有两种情况:
一.先前确定了x在区间(l,r),但是现在发现x在区间(l1,r1),并且两个区间不相交。
二.一个区间的最小值是x,这个区间中有一个子区间的最小值比x更小。
然后我们先考虑第一种情况
先对权值离散化,然后对于每一个权值维护它的交集,如果发现不相交,记录当前回答的位置。
这个位置前的所有回答都不会出现第一种矛盾,且答案一定小于等于当前位置。
所以我们把问题转化为问前几个回答最早在哪里出现第二种矛盾。
我们按权值为第一关键字编号为第二关键字给回答排序。
对于每一个权值像刚才一样求交集。
当交集被大于当前权值的并集包含时,说明出现矛盾。
此时的答案是max(组成当前权值交集的回答的最大编号,交集位置上大于当前权值的区间的编号的最大值(这个用线段树维护));
然后多个区间的交集我们在线段树上记录这多个区间对应的回答的编号的最小值。
- #include<iostream>
- #include<cstring>
- #include<cmath>
- #include<cstdio>
- #include<algorithm>
- #include<map>
- using namespace std;
- const int N=;
- int mal[N],mar[N],b[N],q,m,n,last,ans;
- struct query{
- int l,r,w,id;
- }c[N];
- struct tree{
- int l,r,sum,lazy,mn;
- }tr[];
- bool cmp(query a,query b){
- if(a.w==b.w)return a.id<b.id;
- return a.w>b.w;
- }
- void update(int now){
- tr[now].sum=tr[now*].sum+tr[now*+].sum;
- tr[now].mn=max(tr[now*].mn,tr[now*+].mn);
- }
- void build(int l,int r,int now){
- tr[now].l=l;tr[now].r=r;
- tr[now].lazy=;
- if(l==r){
- tr[now].mn=;
- return;
- }
- int mid=(l+r)>>;
- build(l,mid,now*);
- build(mid+,r,now*+);
- update(now);
- }
- void pushdown(int now){
- if(tr[now].lazy==)return;
- tr[now*].sum=tr[now*].r-tr[now*].l+;
- tr[now*].mn=min(tr[now*].mn,tr[now].lazy);
- tr[now*].lazy=min(tr[now*].lazy,tr[now].lazy);
- tr[now*+].sum=tr[now*+].r-tr[now*+].l+;
- tr[now*+].mn=min(tr[now*+].mn,tr[now].lazy);
- tr[now*+].lazy=min(tr[now*+].lazy,tr[now].lazy);
- tr[now].lazy=;
- }
- void change(int l,int r,int c,int now){
- pushdown(now);
- if(tr[now].l==l&&tr[now].r==r){
- tr[now].sum=tr[now].r-tr[now].l+;
- tr[now].lazy=c;
- tr[now].mn=min(tr[now].mn,c);
- return ;
- }
- int mid=(tr[now].l+tr[now].r)>>;
- if(l>mid)change(l,r,c,now*+);
- else if(r<=mid)change(l,r,c,now*);
- else{
- change(l,mid,c,now*);
- change(mid+,r,c,now*+);
- }
- update(now);
- }
- int getsum(int l,int r,int now){
- pushdown(now);
- if(tr[now].l==l&&tr[now].r==r){
- return tr[now].sum;
- }
- int mid=(tr[now].l+tr[now].r)>>;
- if(l>mid)return getsum(l,r,now*+);
- else if(r<=mid)return getsum(l,r,now*);
- else return getsum(l,mid,now*)+getsum(mid+,r,now*+);
- }
- int getmax(int l,int r,int now){
- pushdown(now);
- if(tr[now].l==l&&tr[now].r==r){
- return tr[now].mn;
- }
- int mid=(tr[now].l+tr[now].r)>>;
- if(l>mid)return getmax(l,r,now*+);
- else if(r<=mid)return getmax(l,r,now*);
- else return max(getmax(l,mid,now*),getmax(mid+,r,now*+));
- }
- int main(){
- scanf("%d%d",&n,&m);
- for(int i=;i<=m;i++){
- scanf("%d%d%d",&c[i].l,&c[i].r,&c[i].w);
- b[i]=c[i].w;
- c[i].id=i;
- }
- sort(b+,b++m);
- int tot=unique(b+,b++m)-b-;
- for(int i=;i<=m;i++){
- c[i].w=lower_bound(b+,b++tot,c[i].w)-b;
- }
- bool flag=false;
- for(int i=;i<=m;i++){
- if(mal[c[i].w]==&&mar[c[i].w]==){
- mal[c[i].w]=c[i].l;
- mar[c[i].w]=c[i].r;
- }
- else{
- if(c[i].l>mar[c[i].w]||c[i].r<mal[c[i].w]){
- q=i-;
- flag=true;
- break;
- }
- else{
- if(mal[c[i].w]<=c[i].l&&c[i].r<=mar[c[i].w]){
- mal[c[i].w]=c[i].l;
- mar[c[i].w]=c[i].r;
- }
- else{
- if(mal[c[i].w]<=c[i].l&&c[i].l<=mar[c[i].w]){
- mal[c[i].w]=c[i].l;
- }
- else if(mal[c[i].w]<=c[i].r&&c[i].r<=mar[c[i].w]){
- mar[c[i].w]=c[i].r;
- }
- }
- }
- }
- }
- build(,n,);
- if(flag==false)q=m;
- sort(c+,c++q,cmp);
- last=;
- for(int i=;i<=q;i++){
- mal[c[i].w]=mar[c[i].w]=;
- }
- ans=min(m,q+);
- for(int i=;i<=q;i++){
- if(c[i].w!=c[i-].w){
- for(int j=last;j<=i-;j++){
- change(c[j].l,c[j].r,c[j].id,);
- }
- last=i;
- }
- if(mal[c[i].w]==&&mar[c[i].w]==){
- mal[c[i].w]=c[i].l;
- mar[c[i].w]=c[i].r;
- }
- else{
- if(mal[c[i].w]<=c[i].l&&c[i].r<=mar[c[i].w]){
- mal[c[i].w]=c[i].l;
- mar[c[i].w]=c[i].r;
- }
- else{
- if(mal[c[i].w]<=c[i].l&&c[i].l<=mar[c[i].w]){
- mal[c[i].w]=c[i].l;
- }
- else if(mal[c[i].w]<=c[i].r&&c[i].r<=mar[c[i].w]){
- mar[c[i].w]=c[i].r;
- }
- }
- }
- if(mar[c[i].w]-mal[c[i].w]+==getsum(mal[c[i].w],mar[c[i].w],)){
- ans=min(ans,max(c[i].id,getmax(mal[c[i].w],mar[c[i].w],)));
- flag=true;
- }
- }
- if(flag==false)printf("");
- else printf("%d",ans);
- return ;
- }
BZOJ 1594 [Usaco2008 Jan]猜数游戏(线段数)的更多相关文章
- bzoj 1594: [Usaco2008 Jan]猜数游戏——二分+线段树
Description 为了提高自己低得可怜的智商,奶牛们设计了一个新的猜数游戏,来锻炼她们的逻辑推理能力. 游戏开始前,一头指定的奶牛会在牛棚后面摆N(1 <= N<= 1,000,00 ...
- BZOJ 1594: [Usaco2008 Jan]猜数游戏 线段树 + 思维 + 二分
Code: #include<bits/stdc++.h> #define maxn 3000000 using namespace std; void setIO(string s) { ...
- bzoj 1594: [Usaco2008 Jan]猜数游戏【二分+线段树】
写错一个符号多调一小时系列-- 二分答案,然后判断这个二分区间是否合法: 先按值从大到小排序,然后对于值相同的一些区间,如果没有交集则不合法:否则把并集在线段树上打上标记,然后值小于这个值的区间们,如 ...
- 【BZOJ 1594】 [Usaco2008 Jan]猜数游戏 (二分+并查集)
1594: [Usaco2008 Jan]猜数游戏 Description 为了提高自己低得可怜的智商,奶牛们设计了一个新的猜数游戏,来锻炼她们的逻辑推理能力. 游戏开始前,一头指定的奶牛会在牛棚后面 ...
- 【BZOJ1594】[Usaco2008 Jan]猜数游戏 二分答案+并查集
[BZOJ1594][Usaco2008 Jan]猜数游戏 Description 为了提高自己低得可怜的智商,奶牛们设计了一个新的猜数游戏,来锻炼她们的逻辑推理能力. 游戏开始前,一头指定的奶牛会在 ...
- Bzoj 1612: [Usaco2008 Jan]Cow Contest奶牛的比赛 传递闭包,bitset
1612: [Usaco2008 Jan]Cow Contest奶牛的比赛 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 891 Solved: 590 ...
- BZOJ 1612: [Usaco2008 Jan]Cow Contest奶牛的比赛( floyd )
对于第 i 头牛 , 假如排名比它高和低的数位 n - 1 , 那么他的 rank 便可以确定 . floyd -------------------------------------------- ...
- [bzoj1594] [Usaco2008 Jan]猜数游戏
二分答案(二分没冲突的前Q-1个问题),用并查集判定(用法同bzoj 1576) 假设一个询问区间[l,r],最小干草堆数目是A,我们可以得出[l,r]上的干草堆数目都>=A. 二分出mid后, ...
- [BZOJ1594] [Usaco2008 Jan]猜数游戏(二分 + 并查集)
传送门 题中重要信息,每堆草的数量都不一样. 可以思考一下,什么情况下才会出现矛盾. 1.如果两个区间的最小值一样,但是这两个区间没有交集,那么就出现矛盾. 2.如果两个区间的最小值一样,并且这两个区 ...
随机推荐
- ZBrush中遮罩的概念及使用
刚接触设计软件的小伙伴有可能不知道什么叫做遮罩,遮罩的概念是什么,顾名思义,遮罩就是可以将局部进行遮挡,使用它可以锁定和保护我们不想改变的模型位置,即被遮罩的部分将不参与任何编辑. ZBrush®软件 ...
- ZBrush中Mrgb、Rgb和M的使用
ZBrush®软件工具架中所有的命令选项都是我们平时较为常用的,位于工具架的中间位置,有一个Mrgb.Rgb和M选项它们所表示的是材质及颜色,那么,在Zbrush中只要选择相应的选项,就可以同时绘制材 ...
- Nusoap复杂对象的的webService制作
推荐网址:http://www.scottnichol.com/nusoapprogwsdl.htm摘抄部分如下:服务器端程序 <?php // Pull in the NuSOAP code ...
- Windows 10快速在指定目录打开命令行
一.我们在想要到达的目录上按住shift键并点击鼠标右键.看到了吗,这时候在弹出菜单里多了一个选项,就是"在此处打开命令窗口",我们点开看一下. 二.不过有时候我们需要以管理员的权 ...
- u-boot启动代码start.S详解360
(1)定义入口.由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本 ...
- vue如何每次打开子组件弹窗都进行初始化
:visible.sync 与 v-if同时使用即可.
- OO第一单元总结__多项式求导问题
作业一.含幂函数的简单多项式的求导 (1)基于度量的程序结构分析 1. 统计信息图: 2. 结构信息图: 3. 复杂度分析 基本复杂度(Essential Complexity (ev(G)).模块设 ...
- 【BZOJ 1297】[SCOI2009]迷路
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 如果点与点之间的距离都是1的话. 那么T次方之后的矩阵上a[1][n]就是所求答案了. 但是这一题的边权可能会大于1 但最多为10 ...
- LaTeX 基本的公式符号命令
本系列文章由 @YhL_Leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50240237 下面列出一些基本的LaT ...
- LeetCode OJ 之 Number of Digit One (数字1的个数)
题目: Given an integer n, count the total number of digit 1 appearing in all non-negative integers les ...