BZOJ 1594 [Usaco2008 Jan]猜数游戏(线段数)

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(组成当前权值交集的回答的最大编号,交集位置上大于当前权值的区间的编号的最大值(这个用线段树维护));

然后多个区间的交集我们在线段树上记录这多个区间对应的回答的编号的最小值。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<cstdio>
  5 #include<algorithm>
  6 #include<map>
  7 using namespace std;
  8 const int N=26000;
  9 int mal[N],mar[N],b[N],q,m,n,last,ans;
 10 struct query{
 11     int l,r,w,id;
 12 }c[N];
 13 struct tree{
 14     int l,r,sum,lazy,mn;
 15 }tr[5000002];
 16 bool cmp(query a,query b){
 17     if(a.w==b.w)return a.id<b.id;
 18     return a.w>b.w;
 19 } 
 20 void update(int now){
 21     tr[now].sum=tr[now*2].sum+tr[now*2+1].sum;
 22     tr[now].mn=max(tr[now*2].mn,tr[now*2+1].mn);
 23 }
 24 void build(int l,int r,int now){
 25     tr[now].l=l;tr[now].r=r;
 26     tr[now].lazy=99999999;
 27     if(l==r){
 28         tr[now].mn=99999999;
 29         return;
 30     }
 31     int mid=(l+r)>>1;
 32     build(l,mid,now*2);
 33     build(mid+1,r,now*2+1);
 34     update(now);
 35 }
 36 void pushdown(int now){
 37     if(tr[now].lazy==99999999)return;
 38     tr[now*2].sum=tr[now*2].r-tr[now*2].l+1;
 39     tr[now*2].mn=min(tr[now*2].mn,tr[now].lazy);
 40     tr[now*2].lazy=min(tr[now*2].lazy,tr[now].lazy);
 41     tr[now*2+1].sum=tr[now*2+1].r-tr[now*2+1].l+1;
 42     tr[now*2+1].mn=min(tr[now*2+1].mn,tr[now].lazy);
 43     tr[now*2+1].lazy=min(tr[now*2+1].lazy,tr[now].lazy);
 44     tr[now].lazy=99999999; 
 45 }
 46 void change(int l,int r,int c,int now){
 47     pushdown(now);
 48     if(tr[now].l==l&&tr[now].r==r){
 49         tr[now].sum=tr[now].r-tr[now].l+1;
 50         tr[now].lazy=c;
 51         tr[now].mn=min(tr[now].mn,c);
 52         return ;
 53     }
 54     int mid=(tr[now].l+tr[now].r)>>1;
 55     if(l>mid)change(l,r,c,now*2+1);
 56     else if(r<=mid)change(l,r,c,now*2);
 57     else{
 58         change(l,mid,c,now*2);
 59         change(mid+1,r,c,now*2+1);
 60     }
 61     update(now); 
 62 }
 63 int getsum(int l,int r,int now){
 64     pushdown(now);
 65     if(tr[now].l==l&&tr[now].r==r){
 66         return tr[now].sum;
 67     }
 68     int mid=(tr[now].l+tr[now].r)>>1;
 69     if(l>mid)return getsum(l,r,now*2+1);
 70     else if(r<=mid)return getsum(l,r,now*2);
 71     else return getsum(l,mid,now*2)+getsum(mid+1,r,now*2+1);
 72 }
 73 int getmax(int l,int r,int now){
 74     pushdown(now);
 75     if(tr[now].l==l&&tr[now].r==r){
 76         return tr[now].mn;
 77     }
 78     int mid=(tr[now].l+tr[now].r)>>1;
 79     if(l>mid)return getmax(l,r,now*2+1);
 80     else if(r<=mid)return getmax(l,r,now*2);
 81     else return max(getmax(l,mid,now*2),getmax(mid+1,r,now*2+1));
 82 }
 83 int main(){
 84     scanf("%d%d",&n,&m);
 85     for(int i=1;i<=m;i++){
 86         scanf("%d%d%d",&c[i].l,&c[i].r,&c[i].w);
 87         b[i]=c[i].w;
 88         c[i].id=i;
 89     }
 90     sort(b+1,b+1+m);
 91     int tot=unique(b+1,b+1+m)-b-1;
 92     for(int i=1;i<=m;i++){
 93         c[i].w=lower_bound(b+1,b+1+tot,c[i].w)-b;
 94     }
 95     bool flag=false;
 96     for(int i=1;i<=m;i++){
 97         if(mal[c[i].w]==0&&mar[c[i].w]==0){
 98             mal[c[i].w]=c[i].l;
 99             mar[c[i].w]=c[i].r;
100         }
101         else{
102             if(c[i].l>mar[c[i].w]||c[i].r<mal[c[i].w]){
103                 q=i-1;
104                 flag=true;
105                 break;
106             }
107             else{
108                 if(mal[c[i].w]<=c[i].l&&c[i].r<=mar[c[i].w]){
109                     mal[c[i].w]=c[i].l;
110                     mar[c[i].w]=c[i].r;
111                 }
112                 else{
113                     if(mal[c[i].w]<=c[i].l&&c[i].l<=mar[c[i].w]){
114                         mal[c[i].w]=c[i].l;
115                     }
116                     else if(mal[c[i].w]<=c[i].r&&c[i].r<=mar[c[i].w]){
117                              mar[c[i].w]=c[i].r;
118                          }
119                 }
120             }
121         }
122     }
123     build(1,n,1);
124     if(flag==false)q=m;
125     sort(c+1,c+1+q,cmp);
126     last=1;
127     for(int i=1;i<=q;i++){
128         mal[c[i].w]=mar[c[i].w]=0;
129     }
130     ans=min(m,q+1);
131     for(int i=1;i<=q;i++){
132         if(c[i].w!=c[i-1].w){
133             for(int j=last;j<=i-1;j++){
134                 change(c[j].l,c[j].r,c[j].id,1);
135             }
136             last=i;
137         }
138         if(mal[c[i].w]==0&&mar[c[i].w]==0){
139             mal[c[i].w]=c[i].l;
140             mar[c[i].w]=c[i].r;
141         }
142         else{
143             if(mal[c[i].w]<=c[i].l&&c[i].r<=mar[c[i].w]){
144                 mal[c[i].w]=c[i].l;
145                 mar[c[i].w]=c[i].r;
146             }
147             else{
148                 if(mal[c[i].w]<=c[i].l&&c[i].l<=mar[c[i].w]){
149                     mal[c[i].w]=c[i].l;
150                 }
151                 else if(mal[c[i].w]<=c[i].r&&c[i].r<=mar[c[i].w]){
152                         mar[c[i].w]=c[i].r;
153                     }
154             }
155         }
156         if(mar[c[i].w]-mal[c[i].w]+1==getsum(mal[c[i].w],mar[c[i].w],1)){
157             ans=min(ans,max(c[i].id,getmax(mal[c[i].w],mar[c[i].w],1)));
158             flag=true;
159         }
160     }
161     if(flag==false)printf("0");
162     else printf("%d",ans);
163     return 0;
164 }

猜你喜欢

转载自www.cnblogs.com/Xu-daxia/p/9561871.html