很容易发现一个O(n2)DP,f[i][j]=f[i][j+1]+f[i+1][j]-f[i+1][j+1]。然后由于有栅栏,一些位置没办法走,然后就可以用类似差分的方法,f[i]表示当前行f[i+1]无法到达的花朵,然后对于每个点找到其下方第一个栅栏。分情况讨论,需要支持单点修改(出现花),区间标记覆盖(出现一个栅栏),以及区间归零(栅栏走了),当然还要区间查询(牛出现了),然后还要支持第一个障碍物的查询,不过这些用一个操作较多的线段树就可以跑过了,复杂度一个log可以“轻松”跑过。

#include<cstdio>
#include<algorithm>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int N=2e6+,M=1e6;
struct fence{int xl,xr,y,i;bool tp;}a[N<<];
bool operator<(fence a,fence b){return a.y!=b.y?a.y>b.y:a.xl<b.xl;}
struct flower{int x,y;}b[N];
bool operator<(flower a,flower b){return a.y>b.y;}
struct cow{int x,y,i;}c[N];
bool operator<(cow a,cow b){return a.y>b.y;}
struct seg{int num;bool cov,cut;}tr[N<<];
int n,m,val[N],ans[N];
void pushup(int rt)
{
tr[rt].num=tr[rt<<].num+tr[rt<<|].num;
tr[rt].cut=tr[rt<<].cut|tr[rt<<|].cut;
}
void modify(int rt){tr[rt].cov=,tr[rt].num=;}
void pushdown(int rt){if(tr[rt].cov)modify(rt<<),modify(rt<<|),tr[rt].cov=;}
void add(int k,int v,int l,int r,int rt)
{
tr[rt].num+=v;
if(l==r)return;
pushdown(rt);
int mid=l+r>>;
if(k<=mid)add(k,v,lson);else add(k,v,rson);
pushup(rt);
}
void cover(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R){modify(rt);return;}
pushdown(rt);
int mid=l+r>>;
if(L<=mid)cover(L,R,lson);
if(R>mid)cover(L,R,rson);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)return tr[rt].num;
pushdown(rt);
int mid=l+r>>,ret=;
if(L<=mid)ret+=query(L,R,lson);
if(R>mid)ret+=query(L,R,rson);
return ret;
}
void update(int k,int l,int r,int rt)
{
if(l==r){tr[rt].cut^=;return;}
pushdown(rt);
int mid=l+r>>;
if(k<=mid)update(k,lson);else update(k,rson);
pushup(rt);
}
int getnxt(int L,int l,int r,int rt)
{
if(l>=L)
{
if(tr[rt].cut)
{
while(l!=r)
if(tr[rt<<].cut)rt<<=,r=l+r>>;
else rt=rt<<|,l=(l+r>>)+;
return l;
}
return ;
}
int tmp,mid=l+r>>;
pushdown(rt);
if(L<=mid&&(tmp=getnxt(L,lson)))return tmp;
return getnxt(L,rson);
}
int main()
{
int f;scanf("%d",&f);
for(int i=,x1,y1,x2,y2;i<f;i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
a[i<<]=(fence){x1,x2,y1-,i,};
a[i<<|]=(fence){x1,x2,y2,i,};
}
sort(a,a+(f<<));
scanf("%d",&m);
for(int i=;i<=m;i++)scanf("%d%d",&b[i].x,&b[i].y);
sort(b+,b+m+);
scanf("%d",&n);
for(int i=;i<=n;i++)scanf("%d%d",&c[i].x,&c[i].y),c[i].i=i;
sort(c+,c+n+);
f=;
update(M,,M,);
for(int i=M,p=,q=;i;i--)
{
int sum,cut;
while(a[f].y==i)
{
if(!a[f].tp)
{
cover(a[f].xl,a[f].xr,,M,);
if(a[f].xl!=)add(a[f].xl-,-val[a[f].i],,M,);
if(a[f].xl!=)update(a[f].xl-,,M,);
if(a[f].xr!=M)update(a[f].xr,,M,);
}
else{
cut=getnxt(a[f].xr,,M,),sum=query(a[f].xl,a[f].xr,,M,);
val[a[f].i]=query(a[f].xr+,cut,,M,);
cover(a[f].xl,a[f].xr,,M,);
if(a[f].xl>)add(a[f].xl-,sum+val[a[f].i],,M,);
if(a[f].xl!=)update(a[f].xl-,,M,);
if(a[f].xr!=M)update(a[f].xr,,M,);
}
f++;
}
while(b[p].y==i)add(b[p].x,,,M,),++p;
while(c[q].y==i)cut=getnxt(c[q].x,,M,),ans[c[q].i]=query(c[q].x,cut,,M,),++q;
}
for(int i=;i<=n;i++)printf("%d\n",ans[i]);
}

BZOJ4422[Cerc2015]Cow Confinement(扫描线+线段树)的更多相关文章

  1. BZOJ4422 : [Cerc2015]Cow Confinement

    从右往左扫描线,用线段树维护扫描线上每一个点能达到的花的数量,并支持最近篱笆的查询. 对于一朵花,找到它上方最近的篱笆,那么它对这中间的每头牛的贡献都是$1$. 当扫到一个篱笆的右边界时,这中间的答案 ...

  2. 【BZOJ-4422】Cow Confinement 线段树 + 扫描线 + 差分 (优化DP)

    4422: [Cerc2015]Cow Confinement Time Limit: 50 Sec  Memory Limit: 512 MBSubmit: 61  Solved: 26[Submi ...

  3. HDU 3642 - Get The Treasury - [加强版扫描线+线段树]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Others) Memory L ...

  4. 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树

    [BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...

  5. HDU 3265/POJ 3832 Posters(扫描线+线段树)(2009 Asia Ningbo Regional)

    Description Ted has a new house with a huge window. In this big summer, Ted decides to decorate the ...

  6. 【bzoj4491】我也不知道题目名字是什么 离线扫描线+线段树

    题目描述 给定一个序列A[i],每次询问l,r,求[l,r]内最长子串,使得该子串为不上升子串或不下降子串 输入 第一行n,表示A数组有多少元素接下来一行为n个整数A[i]接下来一个整数Q,表示询问数 ...

  7. hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积

    题目链接:点击打开链接 题目描写叙述:给定一些矩形,求这些矩形的总面积.假设有重叠.仅仅算一次 解题思路:扫描线+线段树+离散(代码从上往下扫描) 代码: #include<cstdio> ...

  8. P3722 [AH2017/HNOI2017]影魔(单调栈+扫描线+线段树)

    题面传送门 首先我们把这两个贡献翻译成人话: 区间 \([l,r]\) 产生 \(p_1\) 的贡献当且仅当 \(a_l,a_r\) 分别为区间 \([l,r]\) 的最大值和次大值. 区间 \([l ...

  9. Codeforces Gym 101480C - Cow Confinement(扫描线+线段树)

    题面传送门 题意: 有一个 \(10^6\times 10^6\) 的地图.其中 \(m\) 个位置上有花,\(f\) 个矩形外围用栅栏围了起来.保证 \(f\) 个矩形两两之间没有公共点. \(q\ ...

随机推荐

  1. Spring 框架介绍

    Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of Control – I ...

  2. Day 21:网络编程(2)

    以课程中feiQ为例,feiQ作为一个典型的网络编程应用,用一段代码尝试给自己的发送消息 import java.io.IOException; import java.net.DatagramPac ...

  3. c++ opencv显示对话框

    IplImage *pl = cvLoadImage("e:\\3.bmp", 1); cvNamedWindow("123", 1); cvShowImage ...

  4. CSS - 自学笔记

    2018-12-14 ----- 1 所有元素的锚点默认就是它的物理中心 2 改变锚点位置的方法: transform-origin: x-axis y-axis z-axis; 3 ps里在层级里选 ...

  5. JS ~ Promise 对象

    Promise 对象用于表示一个异步操作的最终状态(完成或失败),以及该异步操作的结果值. Promise.all(iterable) 这个方法返回一个新的promise对象,该promise对象在i ...

  6. C++基础--智能指针

    智能指针其实也不是完全的指针,应该说是像指针一样的类对象,智能指针通常有指针的功能,当然同时也包含了一些额外的功能.目前比较常见的智能指针有auto_ptr.unique_ptr和shared_ptr ...

  7. java集合对象区别二

    集合包是Java中最常用的包,它最常用的有Collection和Map两个接口的实现类,Collection用于存放多个单对象,Map用于存放Key-Value形式的键值对. Collection中常 ...

  8. DevOps专题|基础Agent部署系统

    随着京东云业务规模.管理机器规模的扩大,各类agent也在逐渐增多,如日志agent.监控agent.控制系统agent等.这对agent的部署.升级.状态维护提出了很高的要求,一旦某个全局agent ...

  9. axios请求接口的时候带一个参数

    getHomeInfo () { this.axios.get('/api/index.json?city=' + this.city) .then(this.getHomeInfoSucc) } 尽 ...

  10. UVA - 1630 Folding(串折叠)(dp---记忆化搜索)

    题意:给出一个由大写字母组成的长度为n(1<=n<=100)的串,“折叠”成一个尽量短的串.折叠可以嵌套.多解时可输出任意解. 分析: 1.dp[l][r]为l~r区间可折叠成的最短串的长 ...