pre

首先注意一下翻译里面并没有提到的一点,也是让我没看懂样例的一点,就是这个长度为 \(n\) 的数组里面的数各不相同

有很多人用并查集写的这道题,题解里面也有一些用线段树写的,不过我认为我的做法和各位线段树大佬的有些许不同。

solution

同样,单调性和二分查找这里不再赘述,直接说给定 \(n\) 个条件,判断他们是否合法。

根据样例我们可以看出,对于同一个数 \(num\) ,如果给定了多个形如 \([l_i,r_i]->num\) 的条件,是可以缩小这个数的范围的。

通俗的说,我们把线段树上面信息 \(data\) 的意义设置为当前(位置/区间)可以放置的最小的数

那么,当我们拿到这些条件的时候,我们先给条件以 \(num\) 为关键字排序,然后逐一区间修改 \([l_i,r_i]->num\) ,正好可以满足我们的需要,因为一个区间如果最小值为 \(num\) ,那么这个区间内的所有数的最小值都是 \(num\) ,因为之前放的数肯定比当前小,所以直接区间修改即可。

然后我们再次遍历所有条件,看能否找到矛盾。

(墙烈推荐大家根据情况模拟几个例子有利于理解)

情况一:我们查询 \([l_i,r_i]\) 的最小值,发现这个最小值大于 \(num_i\) ,那么直接返回失败。因为出现这种情况当且仅当他的这个区间完全被比他大的数覆盖了,那么必定有矛盾。

情况二:我们查询 \([l_i,r_i]\) 的最小值,发现这个最小值等于 \(num_i\) ,那说明这个条件必定没有矛盾,直接检查下一个即可。

情况三:我们查询 \([l_i,r_i]\) 的最小值,发现这个最小值小于 \(num_i\) ,出现这种情况的唯一可能就是存在一个 \(num_j\) ,他的实际范围被多个条件缩小到了一个范围,然后查询 \([l_i,r_i]\) 的时候有更小的数在这个区间里面,这个时候,我们需要分类讨论。

如果这个比 \(num_i\) 小的数完全包含于 \([l_i,r_i]\) ,那么说明不合法。

否则无法说明不合法,直接去找下一个条件。

code

(放这么丑的代码真是对不起大家的眼睛啦)

#include <cstring>
#include <algorithm>
#include <cstdio>
#define mp make_pair
#define R register int
#define int long
#define printf Ruusupuu = printf int Ruusupuu ; using namespace std ;
typedef long long L ;
typedef long double D ;
typedef unsigned long long G ;
typedef pair< int , int > PI ;
const int N = 1e6 + 10 ;
const int M = 3e4 + 10 ;
const int Inf = 0x3f3f3f3f ; inline int read(){
int w = 0 ; bool fg = 0 ; char ch = getchar() ;
while( ch < '0' || ch > '9' ) fg |= ( ch == '-' ) , ch = getchar() ;
while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch ^ '0' ) , ch = getchar() ;
return fg ? -w : w ;
} int n , q , mid , lx , rx , dlt , fg [N] ;
struct QS{ int l , r , num ; } a [M] , fq [M] , as [M] ;
inline bool cmp( QS a , QS b ){ return a.num < b.num ; } int l [N << 2] , r [N << 2] , data [N << 2] , lz [N << 2] ;
#define ud( x ) data [x] = data [x << 1] < data [x << 1 | 1] ? data [x << 1] : data [x << 1 | 1] ; inline void sp( int x ){
if( !lz [x] ) return ;
int k = lz [x] ; lz [x] = 0 ;
data [x << 1] = lz [x << 1] = data [x << 1 | 1] = lz [x << 1 | 1] = k ;
} void build( int x , int ll , int rr ){
l [x] = ll , r [x] = rr , data [x] = Inf ; lz [x] = 0 ;
if( ll == rr ) return ;
int mid = ( ll + rr ) >> 1 ;
build( x << 1 , ll , mid ) , build( x << 1 | 1 , mid + 1 , rr ) ;
} void cge( int x ){
if( l [x] >= lx && r [x] <= rx ){ data [x] = lz [x] = dlt ; return ; }
sp( x ) ;
int mid = ( l [x] + r [x] ) >> 1 ;
if( lx <= mid ) cge( x << 1 ) ;
if( rx > mid ) cge( x << 1 | 1 ) ;
ud( x ) ;
} int ask( int x ){
if( l [x] >= lx && r [x] <= rx ) return data [x] ;
sp( x ) ;
int mid = ( l [x] + r [x] ) >> 1 , ans = Inf ;
if( lx <= mid ) ans = min( ans , ask( x << 1 ) ) ;
if( rx > mid ) ans = min( ans , ask( x << 1 | 1 ) ) ;
return ans ;
} void sc(){
n = read() , q = read() ;
for( R i = 1 ; i <= q ; i ++ ) a [i].l = read() , a [i].r = read() , a [i].num = read() ;
} inline bool check(){
build( 1 , 1 , n ) ;
for( R i = 1 ; i <= mid ; i ++ ) fq [i] = a [i] , as [i].l = as [i].r = as [i].num = fg [i] = 0 ;
sort( fq + 1 , fq + 1 + mid , cmp ) ; int ls = fq [1].l , rs = fq [1].r , now = fq [1].num , top = 0 ; //多次使用记得清空 for( R i = 2 ; i <= mid ; i ++ ){
if( now != fq [i].num ){
as [++ top].num = now , as [top].l = ls , as [top].r = rs ;
lx = ls , rx = rs , dlt = now , cge( 1 ) ;
now = fq [i].num , ls = fq [i].l , rs = fq [i].r ;
} else{
ls = max( ls , fq [i].l ) , rs = min( rs , fq [i].r ) ;
if( rs < ls ) return 0 ;
}
}
as [++ top].num = now , as [top].l = ls , as [top].r = rs ;
lx = ls , rx = rs , dlt = now , cge( 1 ) ; //先把所有条件都插入 for( R i = 1 ; i <= mid ; i ++ ){
lx = fq [i].l , rx = fq [i].r ;
int sn = ask( 1 ) ;
if( sn > fq [i].num ) return 0 ;
if( sn < fq [i].num ){
for( R j = 1 ; j <= top ; j ++ )
if( as [j].num == sn ){
if( as [j].l >= lx && as [j].r <= rx ) return 0 ;
else break ;
}
}
} // 再逐一寻找矛盾 return 1 ; } void work(){
int lside = 1 , rside = q , ans = 0 ;
while( lside <= rside ){
mid = ( lside + rside ) >> 1 ;
if( check() ) ans = mid , lside = mid + 1 ;
else rside = mid - 1 ;
}
printf( "%ld\n" , ( ans + 1 ) % ( q + 1 ) ) ; //直接一个简洁写法,不用if else
} signed main(){
sc() ;
work() ;
return 0 ;
}

题解—P2898 [USACO08JAN]Haybale Guessing G的更多相关文章

  1. 洛谷 P2898 [USACO08JAN]haybale猜测Haybale Guessing 解题报告

    [USACO08JAN]haybale猜测Haybale Guessing 题目描述 给一段长度为\(n\),每个位置上的数都不同的序列\(a[1\dots n]\)和\(q\)和问答,每个问答是\( ...

  2. [USACO08JAN]Haybale Guessing(LuoguP2898)

    The cows, who always have an inferiority complex about their intelligence, have a new guessing game ...

  3. POJ 3657 Haybale Guessing(区间染色 并查集)

    Haybale Guessing Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2384   Accepted: 645 D ...

  4. Haybale Guessing

    Haybale Guessing Time Limit: 1000MS   Memory Limit: 65536K       Description The cows, who always ha ...

  5. [USACO08JAN]haybale猜测Haybale Guessing

    题目描述 The cows, who always have an inferiority complex about their intelligence, have a new guessing ...

  6. 【[USACO08JAN]haybale猜测Haybale Guessing】

    抄题解.jpg 完全完全不会啊,这道题简直太神了 不过抄题解可真开心 首先这道题目保证了每一个位置上的数都是不同的,那么就能得到第一种判断不合法的方式 如果两个区间的最小值一样,但是两个区间的交集为空 ...

  7. [USACO 08JAN]Haybale Guessing

    Description The cows, who always have an inferiority complex about their intelligence, have a new gu ...

  8. poj-3657 Haybale Guessing(二分答案+并查集)

    http://poj.org/problem?id=3657 下方有中文版,不想看英文的可直接点这里看中文版题目 Description The cows, who always have an in ...

  9. 【题解】[USACO19DEC]Milk Visits G

    题目戳我 \(\text{Solution:}\) 这题不要把思想局限到线段树上--这题大意就是求路径经过的值中\(x\)的出现性问题. 最开始的想法是值域线段树--看了题解发现直接\(vector\ ...

随机推荐

  1. IDEA+Hadoop2.10.1+Zookeeper3.4.10+Hbase 2.3.5 操作JavaAPI

    在此之前要配置好三节点的hadoop集群,zookeeper集群,并启动它们,然后再配置好HBase环境 本文只是HBase2.3.5API操作作相应说明,如果前面环境还没有配置好,可以翻看我之前的博 ...

  2. Android系统编程入门系列之界面Activity交互响应

    在上篇文章中已经了解到界面Activity的绘制完全依赖其加载的视图组件View,不仅如此,用户的每次触摸操作都可以在界面Activity内接收并响应,也可以直接传递给其中的某个视图View响应.本文 ...

  3. F5负载均衡-配置指导手册(含IPv6)

    F5负载均衡-配置手册 设备概况 图形化界面 通过网络形式访问F5任一接口地址,打开浏览器输入https://网络接口地址:或pc机直连F5的MGMT带外管理口,打开浏览器,输入https://192 ...

  4. SpringBoot缓存管理(三) 自定义Redis缓存序列化机制

    前言 在上一篇文章中,我们完成了SpringBoot整合Redis进行数据缓存管理的工作,但缓存管理的实体类数据使用的是JDK序列化方式(如下图所示),不便于使用可视化管理工具进行查看和管理. 接下来 ...

  5. 解决Git Clone速度过慢的方法

    Git Clone速度慢,原因很简单,默认的源是国外的,只需要使用国内源,速度就起飞了(当然,也没有太快,至少可以忍受了).使用方法很简单,在clone某个项目的时候将github.com替换为git ...

  6. Scala学习——操作外部数据

    scala操作外部数据 一.scala读取文件及网络数据 package top.ruandb.scala.Course08 import scala.io.Source object FileApp ...

  7. 微信小程序云开发-云存储的应用-识别通用印刷体

    一.准备工作 1.创建云函数identify 2.云函数identify中index.js代码 1 // 云函数入口文件 2 const cloud = require('wx-server-sdk' ...

  8. 使用Angular CDK实现一个Service弹出Toast组件

    在Angular中,官方团队在开发Material组件库的同时,顺手做了一套Component dev kit,也就是在Angular世界中大名鼎鼎的CDK,这套工具包提供了非常多的前端开发的通用功能 ...

  9. [SqlServer] 理解数据库中的数据页结构

    这边文章,我将会带你深入分析数据库中 数据页 的结构.通过这篇文章的学习,你将掌握如下知识点: 1. 查看一个 表/索引 占用了多少了页. 2. 查看某一页中存储了什么的数据. 3. 验证在数据库中用 ...

  10. 深入刨析tomcat 之---第10篇 how tomcat works 第13章,Response 发送错误信息 sendError

    writedby 张艳涛 在浏览器中发送一个错误应用url 那么tomcat是如何发送错误的呢? 基本上是发送http 的response协议,分为两部分一部分是response设置头信息, 那么先分 ...