1594: [Usaco2008 Jan]猜数游戏

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 626  Solved: 260
[Submit][Status][Discuss]

Description

为了提高自己低得可怜的智商,奶牛们设计了一个新的猜数游戏,来锻炼她们的逻辑推理能力。 游戏开始前,一
头指定的奶牛会在牛棚后面摆N(1 <= N<= 1,000,000)堆干草,每堆有若干捆,并且没有哪两堆中的草一样多。所
有草堆排成一条直线,从左到右依次按1..N编号,每堆中草的捆数在1..1,000,000,000之间。 然后,游戏开始。
另一头参与游戏的奶牛会问那头摆干草的奶牛 Q(1 <= Q <= 25,000)个问题,问题的格式如下: 编号为Ql..Qh(1 
<= Ql <= Qh <= N)的草堆中,最小的那堆里有多少捆草? 对于每个问题,摆干草的奶牛回答一个数字A,但或许
是不想让提问的奶牛那么容易地得到答案,又或许是她自己可能记错每堆中干草的捆数,总之,她的回答不保证是
正确的。 请你帮助提问的奶牛判断一下,摆干草的奶牛的回答是否有自相矛盾之处。

Input

* 第1行: 2个用空格隔开的整数:N 和 Q
* 第2..Q+1行: 每行为3个用空格隔开的整数Ql、Qh、A,描述了一个问题以及它 对应的回答

Output

* 第1行: 如果摆干草的奶牛有可能完全正确地回答了这些问题
(也就是说,能 找到一种使得所有回答都合理的摆放干草的方法),输出0,
否则输出 1个1..Q中的数,表示这个问题的答案与它之前的那些回答有冲突之处
注意:如果有冲突出现输出一个数m,使得前M-1个命题不冲突。

Sample Input

20 4
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个问题“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 ;
}

最新文章

  1. 质数的判断,实现bool IsPrime(int number)
  2. yii2集成富文本编辑器redactor
  3. hadoop常用命令
  4. HBase1.0以上版本的API改变
  5. linux笔记七---------管道
  6. 约束优化方法之拉格朗日乘子法与KKT条件
  7. Dreamweaver SSH Tunneling
  8. C++ STL之set的基本操作
  9. SPOJ_10628_Count_on_a_Tree_(主席树+Tarjan)
  10. Android毛玻璃处理代码(Blur)
  11. python爬虫(5)——正则表达式(二)
  12. JS第一部分--ECMAScript5.0标准语法 (JS基础语法)
  13. C++ 获取程序编译时间
  14. ext4文件系统的delalloc选项造成单次写延迟增加的分析
  15. Centos重新启动网络配置文件,/etc/resolv.conf被覆盖或清空问题解决
  16. Email移动的原理
  17. unidac 6.0.1 与kbmmw 的一点小摩擦
  18. puppet的使用:puppet的hello world
  19. SQLSERVER性能计数器的简单剖析
  20. android aapt 用法 -- ApkReader

热门文章

  1. 面试题sql
  2. 广义线性模型------逻辑回归和softmax回归
  3. Vue文件封装日历组件
  4. BZOJ 2314 士兵的放置(支配集)
  5. [TJOI2015]线性规划
  6. java实验程序基础中的问题总结 java图形化界面
  7. 如何让Jboss的debug在myeclise上运行
  8. maven 构建web项目
  9. Oracle字符乱码、数据越界訪问典型Bug分析
  10. Leetcode--easy系列4