【bzoj1594】猜数游戏
1594: [Usaco2008 Jan]猜数游戏
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 556 Solved: 225
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中的数,表示这个问题的答案与它之前的那些回答有冲突之处
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个问题的回答与这个推断冲突。
HINT
注意:如果有冲突出现输出一个数m,使得前M-1个命题不冲突。
试题分析:首先要确定在什么情况下会出现矛盾:
1.当存在一个(x1,y1,r)与另一个三元组(x,y,r)两个区间不相交时不存在解
2.当存在一个(x1,y1,r1)与另一个三元组(x,y,r)中,r1>r,[x1,y1]包括[x,y],那么显然此情况不合法。
第一个判断只需要顺次判断记录一个交集一个并集即可,第二个判断线段树维护。
此时会发现一个问题,顺次修改并不能判断1在哪里出现矛盾或判断在2出现矛盾。
这样我们就需要考虑二分一个答案,然后检验这个答案以及之前是否会出现矛盾。
先离散化一下r,然后对于每个r求出其询问的交集和并集。
然后我们就可以知道判断1只需要使用交集判断,如果一个r的询问和之前r询问的交集没有相交,那么就矛盾。
对于判断2,从Q~1枚举r,我们的线段树只需要维护一下两个操作:
1.查询区间与运算
2.将一段区间置为1
这是很好维护的,然后注意一点,取区间与需要判断的是交集,而询问中(x,y,r)相当于声明[x,y]这段区间的最小值已经是r了,那么就需要在线段树中将[x并,y并](对于询问答案r的)这一段区间置为1,而不是取交集置为1。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | #include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<algorithm> using namespace std; inline int read(){ int x=0,f=1; char c= getchar (); for (;! isdigit (c);c= getchar ()) if (c== '-' ) f=-1; for (; isdigit (c);c= getchar ()) x=x*10+c- '0' ; return x*f; } const int MAXN = 1000001; const int INF = 999999; int N,Q; struct data{ int x,y,r; int id; }a[MAXN+1]; int ans; int P[MAXN+1],cnt; bool cmp(data a,data b){ return a.r<b.r; } struct row{ int x,y; int x1,y1; }t[MAXN+1]; int tr[MAXN*4+1]; int col[MAXN*4+1]; int mint( int a, int b){ return min((a==INF?-INF:a),(b==INF?-INF:b)); } void Lazy_tage( int l, int r, int rt){ if (!col[rt]) return ; tr[rt*2]=1; tr[rt*2+1]=1; tr[rt]=1; col[rt*2]=1; col[rt*2+1]=1; col[rt]=0; } int Min( int rt, int l, int r, int L, int R){ if (L<=l&&R>=r){ return tr[rt]; } Lazy_tage(l,r,rt); int mid=(l+r)>>1,ans=1; if (mid>=L) ans=ans&Min(rt*2,l,mid,L,R); if (mid<R) ans=ans&Min(rt*2+1,mid+1,r,L,R); return ans; } void Add( int rt, int l, int r, int L, int R){ if (L<=l&&R>=r){ tr[rt]=1; col[rt]=1; return ; } Lazy_tage(l,r,rt); int mid=(l+r)>>1; if (mid>=L) Add(rt*2,l,mid,L,R); if (mid<R) Add(rt*2+1,mid+1,r,L,R); tr[rt]=tr[rt*2]&tr[rt*2+1]; return ; } bool check( int k){ memset (tr,0, sizeof (tr)); memset (col,0, sizeof (col)); for ( int i=1;i<=Q;i++) t[i].x=t[i].y=-1; for ( int i=1;i<=Q;i++){ if (a[i].id>k) continue ; if (t[a[i].r].x==-1){ t[a[i].r].x=a[i].x; //x,y为并集 t[a[i].r].y=a[i].y; t[a[i].r].x1=a[i].x; //x1,y1为交集 t[a[i].r].y1=a[i].y; } else { if (a[i].x>t[a[i].r].y||a[i].y<t[a[i].r].x) return false ; t[a[i].r].x=max(t[a[i].r].x,a[i].x); t[a[i].r].y=min(t[a[i].r].y,a[i].y); t[a[i].r].x1=min(t[a[i].r].x1,a[i].x); t[a[i].r].y1=max(t[a[i].r].y1,a[i].y); } } for ( int i=Q;i>=1;i--){ if (t[i].x!=-1){ int op=Min(1,1,N,t[i].x,t[i].y); //查询r的并集,只有并集中才可能出现r if (op==1) return false ; Add(1,1,N,t[i].x1,t[i].y1); //这里需要将交集加上 } } return true ; } int main(){ N=read(),Q=read(); for ( int i=1;i<=Q;i++){ a[i].x=read(); a[i].y=read(); a[i].r=read(); P[++cnt]=a[i].r; a[i].id=i; } sort(P+1,P+cnt+1); for ( int i=1;i<=Q;i++) a[i].r=lower_bound(P+1,P+cnt+1,a[i].r)-P; //离散化r sort(a+1,a+Q+1,cmp); int l=1,r=Q; while (l<=r){ int mid=(l+r)>>1; if (check(mid)) ans=mid,l=mid+1; else r=mid-1; } printf ( "%d\n" ,(ans+1)%(Q+1)); } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· 趁着过年的时候手搓了一个低代码框架
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· 乌龟冬眠箱湿度监控系统和AI辅助建议功能的实现