[WC2012]记忆中的水杉树
https://www.luogu.org/problemnew/show/P4125
题解
首先一开始所有的线段互不相交。
那么对于第二问来说,一定存在一种方法使得所有线段都朝着一个方向动。
比如说我们要让所有线段从上往下走。
那么上面的线段得向下面的线段连边。
这是一个\(DAG\),考虑怎么建出来。
我们可以先用扫描线,还是因为线段互不相交,所以在扫描线移动的过程中,当前所有线段的相对位置是不变的,所以我们可以把每条线段用斜截式表示,然后用set维护他们的关系,每次插入一条线段就和前驱后继连边就可以了。
然后因为一些恶心的原因得把坐标表示为\((x+1,y)\)。
然后再去考虑第一问,如果直接做的话,感觉需要用数据结构去维护\(DAG\)。
然后我们考虑把操作序列反过来,这样的话删线段就变成了加线段。然后考虑什么情况下加入是不合法的。
比如我们从下往上加线段,设这个线段的横坐标区间为\((l,r)\),那么如果不合法,那么当且仅当这个区间内有在它下面的线段,用上我们刚刚求的拓扑序就是这个线段的拓扑序比较小。
判断的话就线段树维护区间最小值就好了。
因为有四个方向,所以我们还得横纵各做一次扫描线,线段树维护最大值和最小值。
代码
#include<bits/stdc++.h>
#define N 200009
#define inf 2e9
using namespace std;
typedef long long ll;
queue<int>q;
int du[N],tot,head[N],n,xx[N],yy[N],ans[N],_xx[N],_yy[N],tag1[N],tag2[N],c[N],ans2,ans1[N];
ll nowx,b[N<<1];
inline ll rd(){
ll x=0;char c=getchar();bool f=0;
while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x;
}
struct node{int a,b;}mu[N];
struct edge{int n,to;}e[N<<2];
inline void add(int u,int v){e[++tot].n=head[u];e[tot].to=v;head[u]=tot;du[v]++;}
struct point{double x,y;};
struct line{
point x,y;int id;
double k,b;
inline bool operator ==(const line &b)const{
return id==b.id;
}
inline bool operator <(const line &other)const{
return nowx*k+b<nowx*other.k+other.b;
}
}a[N];
struct segment_tree_t{
int mi[N<<2],ma[N<<2],trmi[N<<2],trma[N<<2];
segment_tree_t(){memset(mi,0x3f,sizeof(mi));memset(trmi,0x3f,sizeof(trmi));}
inline void pushdown(int cnt){
mi[cnt<<1]=min(mi[cnt<<1],mi[cnt]);
ma[cnt<<1]=max(ma[cnt<<1],ma[cnt]);
trmi[cnt<<1]=min(trmi[cnt<<1],mi[cnt]);
trma[cnt<<1]=max(trma[cnt<<1],ma[cnt]);
mi[cnt<<1|1]=min(mi[cnt<<1|1],mi[cnt]);
ma[cnt<<1|1]=max(ma[cnt<<1|1],ma[cnt]);
trmi[cnt<<1|1]=min(trmi[cnt<<1|1],mi[cnt]);
trma[cnt<<1|1]=max(trma[cnt<<1|1],ma[cnt]);
ma[cnt]=0;mi[cnt]=inf;
}
inline void ins(int cnt,int l,int r,int L,int R,int x){
if(l>=L&&r<=R){
ma[cnt]=max(ma[cnt],x);
mi[cnt]=min(mi[cnt],x);
trma[cnt]=max(trma[cnt],x);
trmi[cnt]=min(trmi[cnt],x);
return;
}
int mid=(l+r)>>1;
pushdown(cnt);
if(mid>=L)ins(cnt<<1,l,mid,L,R,x);
if(mid<R)ins(cnt<<1|1,mid+1,r,L,R,x);
trmi[cnt]=min(trmi[cnt<<1],trmi[cnt<<1|1]);
trma[cnt]=min(trma[cnt<<1],trma[cnt<<1|1]);
}
inline int querymin(int cnt,int l,int r,int L,int R){
if(l>=L&&r<=R)return trmi[cnt];
int mid=(l+r)>>1,ans=inf;
pushdown(cnt);
if(mid>=L)ans=min(ans,querymin(cnt<<1,l,mid,L,R));
if(mid<R)ans=min(ans,querymin(cnt<<1|1,mid+1,r,L,R));
return ans;
}
inline int querymax(int cnt,int l,int r,int L,int R){
if(l>=L&&r<=R)return trma[cnt];
int mid=(l+r)>>1,ans=0;
pushdown(cnt);
if(mid>=L)ans=max(ans,querymax(cnt<<1,l,mid,L,R));
if(mid<R)ans=max(ans,querymax(cnt<<1|1,mid+1,r,L,R));
return ans;
}
}X,Y;
set<line>s;
set<line>::iterator its;
vector<int>vec[N],anti_vec[N];
vector<int>::iterator it;
int main(){
n=rd();
for(int i=1;i<=n;++i){
a[i].x.x=rd();a[i].x.y=rd();a[i].y.x=rd();a[i].y.y=rd();
if(a[i].x.x>a[i].y.x)swap(a[i].x,a[i].y);
if(a[i].x.x!=a[i].y.x){
a[i].k=(a[i].y.y-a[i].x.y)/(a[i].y.x-a[i].x.x);
a[i].b=a[i].y.y-a[i].y.x*a[i].k;
}
else a[i].b=a[i].y.y;
b[++b[0]]=a[i].x.x+1;b[++b[0]]=a[i].y.x;
}
sort(b+1,b+b[0]+1);
b[0]=unique(b+1,b+b[0]+1)-b-1;
for(int i=1;i<=n;++i){
xx[i]=lower_bound(b+1,b+b[0]+1,a[i].x.x+1)-b;
yy[i]=lower_bound(b+1,b+b[0]+1,a[i].y.x)-b;
a[i].id=i;
vec[xx[i]].push_back(i);
anti_vec[yy[i]].push_back(i);
}
for(int i=1;i<=b[0];++i){
nowx=b[i];
for(it=vec[i].begin();it!=vec[i].end();++it){
line now=a[*it];
its=s.insert(now).first;
++its;
if(its!=s.end()){
add(now.id,its->id);
}
--its;
if(its!=s.begin()){
its--;
add(its->id,now.id);
}
}
for(it=anti_vec[i].begin();it!=anti_vec[i].end();++it){
line now=a[*it];
s.erase(now);
}
vec[i].clear();anti_vec[i].clear();
}
for(int i=1;i<=n;++i)if(!du[i])q.push(i);
while(!q.empty()){
int u=q.front();q.pop();ans[++ans[0]]=u;tag1[u]=ans[0];
for(int i=head[u];i;i=e[i].n){
int v=e[i].to;
if(!--du[v])q.push(v);
}
}
memset(head,0,sizeof(head));tot=0;
for(int i=1;i<=n;++i){
if(a[i].x.y>a[i].y.y)swap(a[i].x,a[i].y);
if(a[i].x.y!=a[i].y.y){
a[i].k=(a[i].y.x-a[i].x.x)/(a[i].y.y-a[i].x.y);
a[i].b=a[i].y.x-a[i].y.y*a[i].k;
}
else a[i].k=0,a[i].b=a[i].y.x;
c[++c[0]]=a[i].x.y+1;;c[++c[0]]=a[i].y.y;
}
sort(c+1,c+c[0]+1);
c[0]=unique(c+1,c+c[0]+1)-c-1;
for(int i=1;i<=n;++i){
_xx[i]=lower_bound(c+1,c+c[0]+1,a[i].x.y+1)-c;
_yy[i]=lower_bound(c+1,c+c[0]+1,a[i].y.y)-c;
a[i].id=i;
vec[_xx[i]].push_back(i);
anti_vec[_yy[i]].push_back(i);
}
for(int i=1;i<=c[0];++i){
nowx=c[i];
for(it=vec[i].begin();it!=vec[i].end();++it){
line now=a[*it];
its=s.insert(now).first;
++its;
if(its!=s.end()){
add(now.id,its->id);
}
--its;
if(its!=s.begin()){
its--;
add(its->id,now.id);
}
}
for(it=anti_vec[i].begin();it!=anti_vec[i].end();++it){
line now=a[*it];
s.erase(now);
}
}
for(int i=1;i<=n;++i)if(!du[i])q.push(i);
while(!q.empty()){
int u=q.front();q.pop();ans1[++ans1[0]]=u;tag2[u]=ans1[0];
for(int i=head[u];i;i=e[i].n){
int v=e[i].to;
if(!--du[v])q.push(v);
}
}
for(int i=1;i<=n;++i){
mu[i].a=rd();mu[i].b=rd();
}
for(int i=n;i>=1;--i){
int id=mu[i].a;
if(mu[i].b==0){
if(Y.querymin(1,1,c[0],_xx[id],_yy[id])<tag2[id]){
ans2=i;
}
}
if(mu[i].b==1){
if(X.querymax(1,1,b[0],xx[id],yy[id])>tag1[id]){
ans2=i;
}
}
if(mu[i].b==2){
if(Y.querymax(1,1,c[0],_xx[id],_yy[id])>tag2[id]){
ans2=i;
}
}
if(mu[i].b==3){
if(X.querymin(1,1,b[0],xx[id],yy[id])<tag1[id]){
ans2=i;
}
}
X.ins(1,1,b[0],xx[id],yy[id],tag1[id]);
Y.ins(1,1,c[0],_xx[id],_yy[id],tag2[id]);
}
printf("%d\n",ans2);
for(int i=1;i<=n;++i)printf("%d %d\n",ans[i],3);
return 0;
}
[WC2012]记忆中的水杉树的更多相关文章
- 洛谷 P4125 [WC2012]记忆中的水杉树【扫描线+set+线段树】
我没有找到能在bzojAC的代码--当然我也WA了--但是我在洛谷过了,那就假装过了吧 minmax线段树一开始写的只能用min更新min,max更新max,实际上是可以互相更新的-- 首先看第二问, ...
- 某寺庙,有小和尚、老和尚若干。有一水缸,由小和尚用水桶从井中提水入缸,老和尚用水桶从缸里取水饮用。水缸可容10桶水,水取自同一井中。水井径窄,每次只能容一个水桶取水。水桶总数为3个。每次入、取缸水仅为1桶,且不可以同时进行。试用P、V操作给出小和尚、老和尚动作的算法描述。
寺庙和尚打水 设信号量mutex_gang, mutex_jing, gang_empty, gang_full, count分别表示使用缸互斥, 使用井互斥, 缸空, 缸满, 水桶总个数 semap ...
- CityEngine中动态水的实现
地址:http://pan.baidu.com/share/link?shareid=3871210059&uk=3492170216 密码:am5b 在今年Esri全球用户大会和Esri中国 ...
- 聊聊Android5.0中的水波纹效果
水波纹效果已经不是什么稀罕的东西了,用过5.0新控件的小伙伴都知道这个效果,可是如果使用一个TextView或者Button或者其它普通控件的话,你是否知道如何给它设置水波纹效果呢?OK,我们今天就来 ...
- 记忆中的像素块褪色了吗?用开源的体素编辑器重新做个 3D 的吧!
本文适合对图形表现有兴趣的美术或者开发人员 本文作者:HelloGitHub-Joey 早期的的显示设备像素颗粒较大,使得显示内容的颗粒感严重,像是由一堆方块组成的.比较好的例子就是 GBA 上的游戏 ...
- 借助Algorithmia网站API:用AI给黑白照片上色,复现记忆中的旧时光
先看DEMOhttps://demos.algorithmia.com/colorize-photos/ 了解ColorfulImageColorizationhttps://algorithmia. ...
- BZOJ 4971: [Lydsy1708月赛]记忆中的背包
神仙构造 分成x个1和一堆>=w-x的大物品 (x<=20 w>=50) 则拼成w的方案中有且仅有一个大物品 若最终序列中有x个1,有一个大物品为w-k,可以提供C(x,k)种方案 ...
- poj1163 【记忆化搜索·水】
题意: 一个这样的三角形,他可以往下的左或者往下的右走.求一个在最后一行的最大. 思路: 额...就是搜一下..记录一下...肯定有重合的情况. code- //#include <bits/s ...
- [bzoj4971]记忆中的背包
为了使得方案的形式较为单一,不妨强制物品体积为1或$\ge \lceil\frac{w}{2}\rceil$,那么假设最终有$x$个1且$\ge \lceil\frac{w}{2}\rceil$的物品 ...
随机推荐
- 《Using Python to Access Web Data》 Week3 Networks and Sockets 课堂笔记
Coursera课程<Using Python to Access Web Data> 密歇根大学 Week3 Networks and Sockets 12.1 Networked Te ...
- Notepad++的tab设置为四个空格
参考:https://www.cnblogs.com/jyfootprint/p/9409934.html 1.Python使用缩进来组织代码块,坚持使用4个空格的缩进. 在文本编辑器中,需要设置把T ...
- SpringBoot(八) -- SpringBoot与Docker
一.Docker简介 Docker是一个开源的应用容器引擎,基于Go语言并遵从Apache2.0协议开源.Docker可以让开发者打包他们的应用以及依赖到一个轻量级,可移植的容器中,然后发布到任何流行 ...
- JAVA总结--jvm
VM,Virtual Machine 即虚拟机,指通过软件模拟的具有完整硬件系统功能的.运行在一个完全隔离环境中的完整计算机系统. JVM,Java Virtual Machine 即Java虚拟机, ...
- Git-第三篇廖雪峰Git教程学习笔记(2)回退修改,恢复文件
1.工作区 C:\fyliu\lfyTemp\gitLocalRepository\yangjie 2.版本库 我们使用git init命令创建的.git就是我们的版本库.Git的版本库里存了很多东西 ...
- Java集合概括总结及集合选用
Collection 1. List ArrayList :Object数组,是一个数组队列,相当于动态数组.它由数组实现,随机访问效率高,随机插入.随机删除效率低. LinkedList :是一个双 ...
- java 泛型的内部原理:类型擦除以及类型擦除带来的问题
一.Java泛型的实现方法:类型擦除前面已经说了,Java的泛型是伪泛型.为什么说Java的泛型是伪泛型呢?因为,在编译期间,所有的泛型信息都会被擦除掉.正确理解泛型概念的首要前提是理解类型擦出(ty ...
- .NET基础篇——利用泛型与反射更新实体(ADO.NET Entity Framework)(转)
自从ADO.NET Entity Framework面世以来,受到大家的热捧,它封装了大量代码生成的工具,用户只需要建立好实体之间的关系,系统就是会为用户自动成功了Add.Delete.CreateO ...
- Vue学习之旅:todomvc的学习练习
一.前奏 1.todomvc官网地址:http://todomvc.com/ 查阅文档和下载插件都可以到这个官网上找. 2.上GitHub上搜索下载有人做的现成的本地模板:进入GitHub搜索todo ...
- ISC2016训练赛 phrackCTF--Classical CrackMe
测试文件:https://static2.ichunqiu.com/icq/resources/fileupload/phrackCTF/REVERSE/CrackMe.rar 1.准备 获得信息 3 ...