BZOJ 1594 [Usaco2008 Jan]猜数游戏(线段数)
1594: [Usaco2008 Jan]猜数游戏
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 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捆。
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个问题的回答与这个推断冲突。
输出说明:
对于第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 }