洛谷 P2898 [USACO08JAN]haybale猜测Haybale Guessing 解题报告
[USACO08JAN]haybale猜测Haybale Guessing
题目描述
给一段长度为\(n\),每个位置上的数都不同的序列\(a[1\dots n]\)和\(q\)和问答,每个问答是\((x, y, r)\)代表\(\min_\limits{i=a}^ba_i= r\), 要你给出最早的有矛盾的那个问答的编号。
输入输出格式
输入格式:
Line 1: Two space-separated integers: \(N\) and \(Q\)
Lines 2..\(Q+1\): Each line contains three space-separated integers that represent a single query and its reply: \(Q_l\), \(Q_h\), and \(A\)
输出格式:
Line 1: Print the single integer \(0\) if there are no inconsistencies among the replies (i.e., if there exists a valid realization of the hay stacks that agrees with all Q queries). Otherwise, print the index from 1..Q of the earliest query whose answer is inconsistent with the answers to the queries before it.
牛客居然考原题...不过题目还是很棒的。
考虑什么情况会产生矛盾。
两段不相交的区间的最小值相同
一个最小值大的区间完全覆盖了一个最小值小的区间
一个区间被其他几个区间完全填充时的,最小值比它们都小。
直接处理很难,如果我们可以按顺序处理的话,比如按最小值从大到小排序,无疑会方便很多,但是回答本身就是带顺序的,我们不可以直接打乱它们。
怎么办呢,二分答案。这无疑是一个很棒的二分答案的思路。正确性很显然。
考虑判断前\(i\)个区间是否产生矛盾,我们按最小值从大到小排序,然后一个一个加入。
- 如果当前区间被其他区间完全覆盖,返回不合法。
- 如果当前区间与其他区间最小值相同
- 如果两个区间不交,返回不合法
- 如果两个区间有交,检查它们的交集是否被别人覆盖,拿它们的并集去覆盖别人。
检查区间覆盖可以通过线段树染色求得,只需要区间赋值\(1\)和区间求和就可以了。
Code:
#include <cstdio>
#include <algorithm>
#include <cstring>
#define rep(i,a,b) for(int i=a;i<=b;i++)
const int N=1e5+10;
int n,q,L[N],R[N],v[N];
struct node
{
int l,r,v,cl,cr;
bool friend operator <(node n1,node n2)
{
return n1.v==n2.v?n1.l<n2.l:n1.v>n2.v;
}
node(){}
node(int l,int r,int v)
{
this->l=l,this->r=r,this->v=v,this->cl=l,this->cr=r;
}
}Q[N],Q0[N];
const int M=4e6+10;
int tag[M],sum[M];
#define ls id<<1
#define rs id<<1|1
void pushdown(int id,int L,int R)
{
if(tag[id])
{
int Mid=L+R>>1;
sum[ls]=Mid+1-L,sum[rs]=R-Mid;
tag[id]=0;tag[ls]=tag[rs]=1;
}
}
int query(int id,int L,int R,int l,int r)
{
if(L==l&&R==r) return sum[id];
pushdown(id,L,R);
int Mid=L+R>>1;
if(r<=Mid) return query(ls,L,Mid,l,r);
else if(l>Mid) return query(rs,Mid+1,R,l,r);
else return query(ls,L,Mid,l,Mid)+query(rs,Mid+1,R,Mid+1,r);
}
void change(int id,int L,int R,int l,int r)
{
if(tag[id]) return;
if(L==l&&R==r)
{
sum[id]=R+1-L,tag[id]=1;
return;
}
int Mid=L+R>>1;
if(r<=Mid) change(ls,L,Mid,l,r);
else if(l>Mid) change(rs,Mid+1,R,l,r);
else change(ls,L,Mid,l,Mid),change(rs,Mid+1,R,Mid+1,r);
sum[id]=sum[ls]+sum[rs];
}
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
bool check(int m)
{
rep(i,1,m) Q[i]=node(L[i],R[i],v[i]);
std::sort(Q+1,Q+1+m);
int m_=0;
rep(i,1,m)
{
if(Q[i].v==Q0[m_].v)
{
if(Q0[m_].r<Q[i].l) return false;
else
{
Q0[m_].l=Q[i].l;
Q0[m_].cr=max(Q0[m_].cr,Q[i].r);
Q0[m_].r=min(Q0[m_].r,Q[i].r);
}
}
else Q0[++m_]=Q[i];
}
memset(tag,0,sizeof(tag));
memset(sum,0,sizeof(sum));
rep(i,1,m_)
{
int l=Q0[i].l,r=Q0[i].r,cl=Q0[i].l,cr=Q0[i].cr;
if(query(1,1,n,l,r)==r+1-l) return false;
change(1,1,n,cl,cr);
}
return true;
}
int main()
{
scanf("%d%d",&n,&q);
rep(i,1,q) scanf("%d%d%d",L+i,R+i,v+i);
int l=1,r=q;
if(check(q)) return puts("0"),0;
while(l<r)
{
int mid=l+r>>1;
if(check(mid)) l=mid+1;
else r=mid;
}
printf("%d\n",l);
return 0;
}
2018.10.29
洛谷 P2898 [USACO08JAN]haybale猜测Haybale Guessing 解题报告的更多相关文章
- 洛谷 P3119 [USACO15JAN]草鉴定Grass Cownoisseur 解题报告
P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 约翰有\(n\)块草场,编号1到\(n\),这些草场由若干条单行道相连.奶牛贝西是美味牧草的鉴赏家,她想到达尽可 ...
- 【洛谷】CYJian的水题大赛 解题报告
点此进入比赛 \(T1\):八百标兵奔北坡 这应该是一道较水的送分题吧. 理论上来说,正解应该是DP.但是,.前缀和优化暴力就能过. 放上我比赛时打的暴力代码吧(\(hl666\)大佬说这种做法的均摊 ...
- 洛谷 P3143 [USACO16OPEN]钻石收藏家Diamond Collector 解题报告
P3143 [USACO16OPEN]钻石收藏家Diamond Collector 题目描述 Bessie the cow, always a fan of shiny objects, has ta ...
- 洛谷 P1337 [JSOI2004]平衡点 / 吊打XXX 解题报告
P1337 [JSOI2004]平衡点 / 吊打XXX 题目描述 有 \(n\) 个重物,每个重物系在一条足够长的绳子上.每条绳子自上而下穿过桌面上的洞,然后系在一起.\(X\)处就是公共的绳结.假设 ...
- 洛谷 P4151 [WC2011]最大XOR和路径 解题报告
P4151 [WC2011]最大XOR和路径 题意 求无向带权图的最大异或路径 范围 思路还是很厉害的,上午想了好一会儿都不知道怎么做 先随便求出一颗生成树,然后每条返祖边都可以出现一个环,从的路径上 ...
- 洛谷 P3258 [JLOI2014]松鼠的新家 解题报告
P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...
- 洛谷 P2420 让我们异或吧 解题报告
P2420 让我们异或吧 题目描述 异或是一种神奇的运算,大部分人把它总结成不进位加法. 在生活中-xor运算也很常见.比如,对于一个问题的回答,是为1,否为0.那么: (A是否是男生 )xor( B ...
- 洛谷 P3102 [USACO14FEB]秘密代码Secret Code 解题报告
P3102 [USACO14FEB]秘密代码Secret Code 题目描述 Farmer John has secret message that he wants to hide from his ...
- 洛谷 P2341 [HAOI2006]受欢迎的牛 解题报告
P2341 [HAOI2006]受欢迎的牛 题目描述 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就是一头明星奶牛.所有奶 牛都是自恋狂,每头奶牛总是喜欢自己的.奶牛之间的"喜欢&q ...
随机推荐
- WebDriver--定位元素的8种方式
在UI层面的自动化测试开发中,元素的定位与操作是基础,也是经常遇到的困难所在.webdriver提供了8种定位: 1. id定位:find_element_by_id("id值") ...
- jenkins配置git+maven+Publish over SSH
一.配置git 1.新建项目,源码管理选择git 2.Repository URL输入git目录 3.Credentials中选择新增凭据,凭据类型选择SSH,usename输入git,passphr ...
- Linux命令应用大词典-第31章 设备管理
31.1 udevadm info:查询udev数据库中的设备信息 31.2 mkdnod:创建块设备和字符设备文件 31.3 MAKEDEV:创建/dev中的设备 31.4 lsblk:列出块设备信 ...
- HDU-1496(哈希表)
Hash入门第一题 题意: 问题描述 考虑具有以下形式的方程: a * x1 ^ 2 + b * x2 ^ 2 + c * x3 ^ 2 + d * x4 ^ 2 = 0 a,b,c,d是来自区间[- ...
- (Python爬虫04)了解通用爬虫和聚焦爬虫,还是理论知识.快速入门可以略过的
如果现在的你返回N年前去重新学习一门技能,你会咋做? 我会这么干: ...哦,原来这个本事学完可以成为恋爱大神啊, 我要掌握精髓需要这么几个要点一二三四..... 具体的学习步骤是这样的一二三.... ...
- leetcode合并区间
合并区间 给出一个区间的集合,请合并所有重叠的区间. 示例 1: 输入: [[1,3],[2,6],[8,10],[15,18]] 输出: [[1,6],[8,10],[15,18]] 解释: ...
- 开关灯问题(C++)
[问题描述] 假设有 N 盏灯(N 为不大于 5000 的正整数),从 1 到 N 按顺序依次编号,初始时全部处于开启状态:有 M 个人(M 为不大于 N 的正整数)也从 1 到 M 依次编号.第一个 ...
- 01背包问题:DP
题目描述: 有 N 件物品和一个容量是 V 的背包.每件物品只能使用一次. 第 i 件物品的体积是 vi,价值是 wi. 求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大.输出 ...
- Python3 小工具-ARP扫描
from scapy.all import * import optparse import threading import os def scan(ipt): pkt=Ether(dst='ff: ...
- js随机数算法
function rnd( seed ){ seed = ( seed * 9301 + 49297 ) % 233280; //为何使用这三个数? return seed / ( 233280.0 ...