我没有找到能在bzojAC的代码……当然我也WA了……但是我在洛谷过了,那就假装过了吧

minmax线段树一开始写的只能用min更新min,max更新max,实际上是可以互相更新的……

首先看第二问,注意到因为没有相交,所以可以全都按某种顺序像同一个方向移动来完成游戏,这个顺序通过扫描线找到,用set维护经过当前x坐标的的线段的y坐标,具体用y=kx+b的形式维护,因为不相交,所以随着x的变化,线段的y点的大小关系不会改变;每次插入一个点的时候,找一下它的前驱后继,分别连边(这里的前驱后继就相当于向上和向下第一个撞上的线段),然后得到一张有向图,拓扑序就是游戏的操作顺序

然后看第一问,对横向和纵向都做一遍拓扑,记录点在拓扑序中的出现的时间,然后用两个线段树分别维护对于横向/纵向点的出现时间的最大最小值,然后倒着做,每次查询线段树里就相当于查询游戏中剩下的线段的出现时间,判一下合法即可

#include<iostream>
#include<cstdio>
#include<set>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=300005;
int n,p[N],q[N],d[N],r[2][N],hs[2][N],ht[2][N],c[N],wi,h[N],cnt,tp[N],ans;
struct dian
{
int x,y;
}a[N],b[N];
struct bian
{
int ne,to;
}e[N<<1];
struct xds
{
int l,r,mn,mx,lmn,lmx;
void add(int v)
{
if(v<mn)
mn=v;
if(v>mx)
mx=v;
if(v<lmn)
lmn=v;
if(v>lmx)
lmx=v;
}
};
struct qwe
{
int x,id,f;
double k,b;
qwe(int X=0,int ID=0,int F=0,double K=0,double B=0)
{
x=X,id=ID,f=F,k=K,b=B;
}
bool operator < (const qwe &z) const
{
return k*wi+b<z.k*wi+z.b;
}
bool operator == (const qwe &z) const
{
return id==z.id;
}
}f[N<<1];
bool cmp(const qwe &a,const qwe &b)
{
return a.x<b.x||(a.x==b.x&&a.f>b.f);
}
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
void add(int u,int v)
{//cerr<<u<<" "<<v<<endl;
cnt++;
e[cnt].ne=h[u];
e[cnt].to=v;
h[u]=cnt;
d[v]++;
}
void wk(int hs[],int ht[],int r[])
{
int tot=0,has=0;
for(int i=1;i<=n;i++)
c[++tot]=a[i].x+1,c[++tot]=b[i].x;
sort(c+1,c+1+tot);
for(int i=1;i<=tot;i++)
if(i==1||c[i]!=c[i-1])
c[++has]=c[i];
tot=0;
for(int i=1;i<=n;i++)
{
hs[i]=lower_bound(c+1,c+1+has,a[i].x+1)-c,ht[i]=lower_bound(c+1,c+1+has,b[i].x)-c;
f[++tot]=qwe(hs[i],i,1,(double)(b[i].y-a[i].y)/(double)(b[i].x-a[i].x),a[i].y-a[i].x*(double)(b[i].y-a[i].y)/(double)(b[i].x-a[i].x));
f[++tot]=qwe(ht[i],i,-1,(double)(b[i].y-a[i].y)/(double)(b[i].x-a[i].x),a[i].y-a[i].x*(double)(b[i].y-a[i].y)/(double)(b[i].x-a[i].x));
}
sort(f+1,f+1+tot,cmp);
memset(d,0,sizeof(d));
memset(h,0,sizeof(h));
cnt=0;
set<qwe>s;
set<qwe>::iterator it;
for(int i=1,w=1;i<=has;i++)
{
wi=c[i];
while(w<=tot&&f[w].x==i)
{
if(f[w].f==1)
{
it=s.lower_bound(f[w]);
if(it!=s.end())
add(f[w].id,it->id);
if(it!=s.begin())
add((--it)->id,f[w].id);
s.insert(f[w]);
}
else
s.erase(f[w]);
w++;
}
}
tot=0;
queue<int>q;
for(int i=1;i<=n;i++)
if(!d[i])
q.push(i);
while(!q.empty())
{
int u=q.front();
r[u]=++tot;
q.pop();
for(int i=h[u];i;i=e[i].ne)
if(!(--d[e[i].to]))
q.push(e[i].to);
}
}
struct clc
{
xds t[N<<2];
void build(int ro,int l,int r)
{
t[ro].l=l,t[ro].r=r,t[ro].mx=t[ro].lmx=-1e9,t[ro].mn=t[ro].lmn=1e9;
if(l==r)
return;
int mid=(l+r)>>1;
build(ro<<1,l,mid);
build(ro<<1|1,mid+1,r);
}
void pd(int ro)
{
if(t[ro].lmx!=-1e9)
{
t[ro<<1].add(t[ro].lmx);
t[ro<<1|1].add(t[ro].lmx);
t[ro].lmx=-1e9;
}
if(t[ro].lmn!=1e9)
{
t[ro<<1].add(t[ro].lmn);
t[ro<<1|1].add(t[ro].lmn);
t[ro].lmn=1e9;
}
}
void update(int ro,int l,int r,int v)
{
if(t[ro].l==l&&t[ro].r==r)
{
t[ro].add(v);
return;
}
pd(ro);
int mid=(t[ro].l+t[ro].r)>>1;
if(r<=mid)
update(ro<<1,l,r,v);
else if(l>mid)
update(ro<<1|1,l,r,v);
else
update(ro<<1,l,mid,v),update(ro<<1|1,mid+1,r,v);
t[ro].mn=min(t[ro<<1].mn,t[ro<<1|1].mn);
t[ro].mx=max(t[ro<<1].mx,t[ro<<1|1].mx);
}
pair<int,int>ques(int ro,int l,int r)
{
if(t[ro].l==l&&t[ro].r==r)
return make_pair(t[ro].mn,t[ro].mx);
pd(ro);
int mid=(t[ro].l+t[ro].r)>>1;
if(r<=mid)
return ques(ro<<1,l,r);
else if(l>mid)
return ques(ro<<1|1,l,r);
else
{
pair<int,int>x=ques(ro<<1,l,mid),y=ques(ro<<1|1,mid+1,r);
return make_pair(min(x.first,y.first),max(x.second,y.second));
}
}
}t0,t1;
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
a[i].x=read(),a[i].y=read(),b[i].x=read(),b[i].y=read();
if(a[i].x>b[i].x)
swap(a[i],b[i]);
}
wk(hs[0],ht[0],r[0]);//cerr<<"OK"<<endl;
for(int i=1;i<=n;i++)
{
swap(a[i].x,a[i].y),swap(b[i].x,b[i].y);
if(a[i].x>b[i].x)
swap(a[i],b[i]);
}
wk(hs[1],ht[1],r[1]);
// for(int i=1;i<=n;i++)
// cerr<<r[0][i]<<" ";cerr<<endl;
// for(int i=1;i<=n;i++)
// cerr<<r[1][i]<<" ";cerr<<endl;
t0.build(1,1,2*n);
t1.build(1,1,2*n);
for(int i=1;i<=n;i++)
p[i]=read(),q[i]=read();
for(int i=n;i>=1;i--)
{
if(q[i]==1||q[i]==3)
{
pair<int,int>nw=t0.ques(1,hs[0][p[i]],ht[0][p[i]]);
if((q[i]==1&&nw.second>r[0][p[i]])||(q[i]==3&&nw.first<r[0][p[i]]))
ans=i;
}
else
{
pair<int,int>nw=t1.ques(1,hs[1][p[i]],ht[1][p[i]]);//cerr<<nw.first<<" "<<nw.second<<endl;
if((q[i]==2&&nw.second>r[1][p[i]])||(q[i]==0&&nw.first<r[1][p[i]]))
ans=i;
}
t0.update(1,hs[0][p[i]],ht[0][p[i]],r[0][p[i]]);
t1.update(1,hs[1][p[i]],ht[1][p[i]],r[1][p[i]]);
}
printf("%d\n",ans);
for(int i=1;i<=n;i++)
tp[r[0][i]]=i;
for(int i=1;i<=n;i++)
printf("%d 3\n",tp[i]);
return 0;
}

洛谷 P4125 [WC2012]记忆中的水杉树【扫描线+set+线段树】的更多相关文章

  1. [WC2012]记忆中的水杉树

    https://www.luogu.org/problemnew/show/P4125 题解 首先一开始所有的线段互不相交. 那么对于第二问来说,一定存在一种方法使得所有线段都朝着一个方向动. 比如说 ...

  2. BZOJ5291/洛谷P4458/LOJ#2512 [Bjoi2018]链上二次求和 线段树

    原文链接http://www.cnblogs.com/zhouzhendong/p/9031130.html 题目传送门 - LOJ#2512 题目传送门 - 洛谷P4458 题目传送门 - BZOJ ...

  3. 「BZOJ2733」「洛谷3224」「HNOI2012」永无乡【线段树合并】

    题目链接 [洛谷] 题解 很明显是要用线段树合并的. 对于当前的每一个连通块都建立一个权值线段树. 权值线段树处理操作中的\(k\)大的问题. 如果需要合并,那么就线段树暴力合并,时间复杂度是\(nl ...

  4. 【洛谷4770】 [NOI2018]你的名字(SAM,线段树合并)

    传送门 洛谷 Solution 做过的比较玄学的后缀自动机. 果然就像\(Tham\)所讲,后缀自动机这种东西考场考了不可能做的出来的... 考虑如果\(l=1,r=|S|\)的怎么做? 直接建后缀自 ...

  5. 洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree

    原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L.. ...

  6. 洛谷P4632 [APIO2018] New Home 新家(动态开节点线段树 二分答案 扫描线 set)

    题意 题目链接 Sol 这题没有想象中的那么难,但也绝对不简单. 首先把所有的询问离线,按照出现的顺序.维护时间轴来处理每个询问 对于每个询问\((x_i, y_i)\),可以二分答案\(mid\). ...

  7. 洛谷P3994 Highway(树形DP+斜率优化+可持久化线段树/二分)

    有点类似NOI2014购票 首先有方程$f(i)=min\{f(j)+(dep_i-dep_j)*p_i+q_i\}$ 这个显然是可以斜率优化的... $\frac {f(j)-f(k)}{dep_j ...

  8. 洛谷大宁的邀请赛~元旦祭F: U17264 photo(线段树)

    标程的写法稍微有点麻烦,其实不需要平衡树也是可以做的. 线段树上维护从左端点开始最远的有拍照的长度,以及区间的最大值. 考虑两段区间合并的时候,显然左区间必须取,右区间的第一个比左区间最大值大的数开始 ...

  9. 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间合并(单点更新、区间查询)

    P4513 小白逛公园 题目背景 小新经常陪小白去公园玩,也就是所谓的遛狗啦… 题目描述 在小新家附近有一条“公园路”,路的一边从南到北依次排着nn个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩 ...

随机推荐

  1. 【转载】Http协议与TCP协议简单理解

    在C#编写代码,很多时候会遇到Http协议或者TCP协议,这里做一个简单的理解.TCP协议对应于传输层,而HTTP协议对应于应用层,从本质上来说,二者没有可比性.Http协议是建立在TCP协议基础之上 ...

  2. 面试-1-C#浅解

    面试-1   C#浅解众所周知c#是微软推出的一款完全没面向对象的编程语言,那么对象是什么?在现实生活中人们一提到对象首先想到的就是“情侣”!但是在我们的程序中对象是什么? 在程序中个能够区别于其他事 ...

  3. Java单例的实现

    1.声明实例变量(静态) 2.私有化构造函数 3.创建获取实例的方法 public class Singleton{ //创建实例变量 private static Singleton singlet ...

  4. 性能问题案例02——sybase连接堵塞问题

    现象:近期现场反馈一个问题.系统在审批的时候,常常卡死.整个系统全然用不了,浏览器訪问处于loading的状态. 排查: 1.一般系统挂了首先想到内存问题,可是现象是loading,也就是说没有挂,线 ...

  5. Iterator && Iterable Collection && Map

    Java集合类库将集合的接口与实现分离.同样的接口,可以有不同的实现. Java集合类的基本接口是Collection接口.而Collection接口必须实现Iterable接口. 以下图表示集合框架 ...

  6. vscode部分文件夹无法打开

    vscode部分文件夹无法打开,无法正常显示 解决方案:关闭该IDE.找到C:\Users\XX\AppData\Roaming\Code,将Code文件夹删除.重新打开vsCode,即可恢复.但是以 ...

  7. Tomcat启动报:invalid LOC header (bad signature)的问题

    原因:这种一般是因为项目依赖的某个jar包损坏引起的, 解决办法: 1.右键项目,选择maven,更新(update maven project) 2.通过右击项目名 ->  Run as -& ...

  8. POJ3080 Blue Jeans —— 暴力枚举 + KMP / strstr()

    题目链接:https://vjudge.net/problem/POJ-3080 Blue Jeans Time Limit: 1000MS   Memory Limit: 65536K Total ...

  9. vue开发:移动端图片上传

    因为最近遇到个移动端上传头像的需求,上传到后台的数据是base64位,其中为了提高用户体验,把比较大的图片用canvas进行压缩之后再进行上传.在移动端调用拍照功能时,会发生图片旋转,为了解决这个问题 ...

  10. 解决 git branch -a 无法全部显示远程的分支,只显示master分支

    新建分支 若遇到 git branch -a 无法全部显示远程的分支,只显示master分支 可以通过 git fetch 将本地远程跟踪分支进行更新,与远程分支保持一致