【BZOJ-4422】Cow Confinement 线段树 + 扫描线 + 差分 (优化DP)
4422: [Cerc2015]Cow Confinement
Time Limit: 50 Sec Memory Limit: 512 MB
Submit: 61 Solved: 26
[Submit][Status][Discuss]
Description

Input
Output
Sample Input
2 2 8 4
1 9 4 10
6 7 9 9
3 3 7 3
9
3 4
8 4
11 5
10 7
10 8
9 8
2 8
4 11
9 11
8
1 1
5 10
6 9
3 7
7 1
4 2
7 5
3 3
Sample Output
1
0
1
3
1
3
0
HINT
Source
Solution
一道idea非常好的题
首先这题可以DP,不过转移之类的需要讨论,比较麻烦
$dp[i][j]=\begin{Bmatrix} 0(下面和右面都有栅栏)\\ dp[i+1][j](右面有栅栏)\\ dp[i][j+1](下面有栅栏)\\ dp[i+1][j]+dp[i][j+1]-dp[i+1][j+1]((i+1,j+1)不是栅栏的左上角)\\ dp[i+1][j]+dp[i][j+1]-dp[x+1][y+1]((i+1,j+1)是左上角,(x,y)是右下角)& & \end{Bmatrix}+flower[i][j]$
这样DP的时间复杂度是$O((N+F+M)^{2})$的
那么考虑优化这个DP
差分出$f[i][j]$表示$(i,j)$能得到,但$(i,j-1)$不能得到的花的数量
那么考虑扫描线,从右往左
那讨论一下各种情况,
遇到花单点数值+1;遇到一个未出现过的栅栏,区间查询和,单点修改数值,区间修改覆盖0;删除一个栅栏,区间修改覆盖0;遇见一头牛,找到下方第一个栅栏,区间求和;
显然都可以用线段树维护
查找下方第一个栅栏?维护一个最小即可
时间复杂度是$O(10^{6}log10^{6})$
实现起来有一些细节,线段树中需要加特判,当所需要修改的坐标为0啊之类的
Code
- #include<iostream>
- #include<cstdio>
- #include<algorithm>
- #include<cstring>
- #include<cmath>
- using namespace std;
- inline int read()
- {
- int x=,f=; char ch=getchar();
- while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
- while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
- return x*f;
- }
- #define MAXY 1000000
- #define MAXF 200010
- #define MAXN 200010
- #define MAXM 200010
- int F,M,N;
- struct FenceNode{int x1,x2,y1,y2;}fen[MAXF];
- struct CowNode{int x,y,id;}cow[MAXN];
- struct FlowerNode{int x,y;}flo[MAXM];
- struct LineNode{int y,x1,x2,id,f;}line[MAXF<<]; int tp;
- struct SegmentTreeNode{int l,r,tag,bk,sum;}tree[MAXY<<];
- int tmp[MAXF],ans[MAXN];
- inline void Update(int now)
- {
- tree[now].bk=min(tree[now<<].bk,tree[now<<|].bk);
- tree[now].sum=tree[now<<].sum+tree[now<<|].sum;
- }
- inline void PushDown(int now)
- {
- if (!tree[now].tag || tree[now].l==tree[now].r) return;
- tree[now].tag=;
- tree[now<<].sum=; tree[now<<|].sum=;
- tree[now<<].tag=; tree[now<<|].tag=;
- }
- inline void BuildTree(int now,int l,int r)
- {
- tree[now].l=l,tree[now].r=r;
- tree[now].sum=; tree[now].tag=; tree[now].bk=MAXY;
- if (l==r) return;
- int mid=(l+r)>>;
- BuildTree(now<<,l,mid);
- BuildTree(now<<|,mid+,r);
- Update(now);
- }
- inline void PointChangeSum(int now,int pos,int D)
- {
- if (pos==MAXY+ || pos==) return;
- int l=tree[now].l,r=tree[now].r;
- PushDown(now);
- if (l==r) {tree[now].sum+=D; return;}
- int mid=(l+r)>>;
- if (pos<=mid) PointChangeSum(now<<,pos,D);
- if (pos>mid) PointChangeSum(now<<|,pos,D);
- Update(now);
- }
- inline void PointChangeBreak(int now,int pos,int D)
- {
- if (pos==MAXY+ || pos==) return;
- int l=tree[now].l,r=tree[now].r;
- PushDown(now);
- if (l==r) {tree[now].bk=D? l:MAXY; return;}
- int mid=(l+r)>>;
- if (pos<=mid) PointChangeBreak(now<<,pos,D);
- if (pos>mid) PointChangeBreak(now<<|,pos,D);
- Update(now);
- }
- inline void IntervalChange(int now,int L,int R)
- {
- if (L== || R==MAXY+ || R<L) return;
- int l=tree[now].l,r=tree[now].r;
- PushDown(now);
- if (L<=l && R>=r) {tree[now].tag=; tree[now].sum=; return;}
- int mid=(l+r)>>;
- if (L<=mid) IntervalChange(now<<,L,R);
- if (R>mid) IntervalChange(now<<|,L,R);
- Update(now);
- }
- inline int IntervalQuerySum(int now,int L,int R)
- {
- if (L== || R==MAXY+ || R<L) return ;
- int l=tree[now].l,r=tree[now].r;
- PushDown(now);
- if (L<=l && R>=r) return tree[now].sum;
- int mid=(l+r)>>,re=;
- if (L<=mid) re+=IntervalQuerySum(now<<,L,R);
- if (R>mid) re+=IntervalQuerySum(now<<|,L,R);
- return re;
- }
- inline int IntervalQueryBreak(int now,int L,int R)
- {
- if (L== || R==MAXY+ || R<L) return ;
- int l=tree[now].l,r=tree[now].r;
- PushDown(now);
- if (L<=l && R>=r) return tree[now].bk;
- int mid=(l+r)>>,re=MAXY;
- if (L<=mid) re=min(re,IntervalQueryBreak(now<<,L,R));
- if (R>mid) re=min(re,IntervalQueryBreak(now<<|,L,R));
- return re;
- }
- inline bool cmpLine(LineNode A,LineNode B) {return A.y!=B.y? A.y>B.y : A.x1<B.x1;}
- inline bool cmpCow(CowNode A,CowNode B) {return A.y>B.y;}
- inline bool cmpFlower(FlowerNode A,FlowerNode B) {return A.y>B.y;}
- int main()
- {
- F=read();
- for (int i=; i<=F; i++) fen[i].x1=read(),fen[i].y1=read(),fen[i].x2=read(),fen[i].y2=read();
- for (int i=; i<=F; i++)
- line[++tp]=(LineNode){fen[i].y1-,fen[i].x1,fen[i].x2,i,-},
- line[++tp]=(LineNode){fen[i].y2,fen[i].x1,fen[i].x2,i,};
- sort(line+,line+tp+,cmpLine);
- M=read();
- for (int i=; i<=M; i++) flo[i].x=read(),flo[i].y=read();
- sort(flo+,flo+M+,cmpFlower);
- N=read();
- for (int i=; i<=N; i++) cow[i].x=read(),cow[i].y=read(),cow[i].id=i;
- sort(cow+,cow+N+,cmpCow);
- BuildTree(,,MAXY);
- int nowl=,nowf=,nowc=,next,sum;
- for (int i=MAXY; i; i--)
- {
- while (line[nowl].y==i)
- {
- if (line[nowl].f==-)
- {
- IntervalChange(,line[nowl].x1,line[nowl].x2);
- PointChangeSum(,line[nowl].x1-,-tmp[line[nowl].id]);
- PointChangeBreak(,line[nowl].x1-,);
- PointChangeBreak(,line[nowl].x2,);
- }
- else
- {
- next=IntervalQueryBreak(,line[nowl].x2,MAXY);
- sum=IntervalQuerySum(,line[nowl].x1,line[nowl].x2);
- tmp[line[nowl].id]=IntervalQuerySum(,line[nowl].x2+,next);
- IntervalChange(,line[nowl].x1,line[nowl].x2);
- PointChangeSum(,line[nowl].x1-,sum+tmp[line[nowl].id]);
- PointChangeBreak(,line[nowl].x1-,);
- PointChangeBreak(,line[nowl].x2,);
- }
- nowl++;
- }
- while (flo[nowf].y==i)
- PointChangeSum(,flo[nowf].x,),nowf++;
- while (cow[nowc].y==i)
- next=IntervalQueryBreak(,cow[nowc].x,MAXY),
- ans[cow[nowc].id]=IntervalQuerySum(,cow[nowc].x,next),
- nowc++;
- }
- for (int i=; i<=N; i++) printf("%d\n",ans[i]);
- return ;
- }
- #include<cstdio>
- #include<iostream>
- using namespace std;
- #include<cstring>
- #include<cmath>
- #include<algorithm>
- const int X=1e6+,Y=1e6,F=2e5+,M=2e5+,N=2e5+;
- char * cp=(char *)malloc();
- void in(int &x){
- while(*cp<''||*cp>'')++cp;
- for(x=;*cp>=''&&*cp<='';)x=x*+(*cp++^'');
- }
- struct FenS{
- int xl,xr;
- int y;
- int i;
- bool flag;
- bool operator < (const FenS & o)const{
- return y!=o.y?y>o.y:xl<o.xl;
- }
- }fence[F<<];
- int fsum[F];
- struct FloS{
- int x,y;
- bool operator < (const FloS & o)const{
- return y>o.y;
- }
- }flower[M];
- struct CS{
- int x,y;
- int i;
- bool operator < (const CS & o)const{
- return y>o.y;
- }
- }cow[N];
- int ans[N];
- struct SS{
- int cnt;
- bool cover;
- bool barrier;
- }segt[X<<];
- #define lson node<<1,l,l+r>>1
- #define rson node<<1|1,(l+r>>1)+1,r
- void out(int node,int l,int r){
- printf("segt[%d][%d,%d]={cnt=%d,cover=%d,barrier=%d}\n",node,l,r,segt[node].cnt,segt[node].cover,segt[node].barrier);
- }
- void pushup(int node){
- segt[node].cnt=segt[node<<].cnt+segt[node<<|].cnt;
- segt[node].barrier=segt[node<<].barrier|segt[node<<|].barrier;
- }
- void paint(int node){
- //printf("paint(%d)\n",node);
- segt[node].cover=;
- segt[node].cnt=;
- }
- void pushdown(int node){
- if(segt[node].cover){
- paint(node<<),paint(node<<|);
- segt[node].cover=;
- }
- }
- void add(int node,int l,int r,int x,int delta){
- //printf("add(%d,%d,%d,%d,%d)\n",node,l,r,x,delta);
- //out(node,l,r);
- segt[node].cnt+=delta;
- if(l!=r){
- pushdown(node);
- if(x<=l+r>>)add(lson,x,delta);
- else add(rson,x,delta);
- pushup(node);
- }
- //printf("add:");
- //out(node,l,r);
- }
- void cover(int node,int l,int r,int L,int R){
- //out(node,l,r);
- if(L<=l&&r<=R)paint(node);
- else{
- pushdown(node);
- if(L<=l+r>>)cover(lson,L,R);
- if(R>l+r>>)cover(rson,L,R);
- pushup(node);
- }
- }
- int query_cnt(int node,int l,int r,int L,int R){
- //printf("query(%d,%d,%d,%d,%d)\n",node,l,r,L,R);
- if(L<=l&&r<=R){
- //printf("query_cnt get [%d][%d,%d]=%d\n",node,l,r,segt[node].cnt);
- return segt[node].cnt;
- }
- else{
- pushdown(node);
- int ans=;
- if(L<=l+r>>)ans+=query_cnt(lson,L,R);
- if(R>l+r>>)ans+=query_cnt(rson,L,R);
- return ans;
- }
- }
- void update(int node,int l,int r,int x){
- if(l==r)segt[node].barrier^=;
- else{
- pushdown(node);
- if(x<=l+r>>)update(lson,x);
- else update(rson,x);
- pushup(node);
- }
- //printf("update:");
- //out(node,l,r);
- }
- int query_barrier(int node,int l,int r,int L){
- if(l>=L){
- //printf("Query_barrier Get ");
- //out(node,l,r);
- if(segt[node].barrier){
- while(l!=r)
- if(segt[node<<].barrier)node<<=,r=l+r>>;
- else node=node<<|,l=(l+r>>)+;
- return l;
- }
- else return ;
- }
- else{
- int tmp;
- pushdown(node);
- if(L<=l+r>>&&(tmp=query_barrier(lson,L)))return tmp;
- else return query_barrier(rson,L);
- }
- }
- int main(){
- freopen("cow.in","r",stdin);
- freopen("cow.out","w",stdout);
- fread(cp,,,stdin);
- int f;
- in(f);
- int x1,y1,x2,y2;
- for(int i=f;i--;){
- in(x1),in(y1),in(x2),in(y2);
- fence[i<<]=(FenS){x1,x2,y1-,i,};
- fence[i<<|]=(FenS){x1,x2,y2,i,};
- }
- sort(fence,fence+(f<<));
- int m;
- in(m);
- for(int i=m;i--;)in(flower[i].x),in(flower[i].y);
- sort(flower,flower+m);
- int n;
- in(n);
- for(int i=;i<n;++i){
- in(cow[i].x),in(cow[i].y);
- cow[i].i=i;
- }
- sort(cow,cow+n);
- f=m=n=;
- update(,,Y,Y);
- int sum,br;
- for(int i=Y;i;--i){
- //printf("----%d----\n",i);
- for(;fence[f].y==i;++f)
- if(fence[f].flag==){
- cover(,,Y,fence[f].xl,fence[f].xr);
- if(fence[f].xl!=)add(,,Y,fence[f].xl-,-fsum[fence[f].i]);
- if(fence[f].xl!=)update(,,Y,fence[f].xl-);
- if(fence[f].xr!=Y)update(,,Y,fence[f].xr);
- }
- else{
- br=query_barrier(,,Y,fence[f].xr);
- sum=query_cnt(,,Y,fence[f].xl,fence[f].xr);
- fsum[fence[f].i]=query_cnt(,,Y,fence[f].xr+,br);
- cover(,,Y,fence[f].xl,fence[f].xr);
- if(fence[f].xl>)add(,,Y,fence[f].xl-,sum+fsum[fence[f].i]);
- if(fence[f].xl!=)update(,,Y,fence[f].xl-);
- if(fence[f].xr!=Y)update(,,Y,fence[f].xr);
- }
- for(;flower[m].y==i;++m){
- //cout<<flower[m].x<<","<<flower[m].y<<endl;
- add(,,Y,flower[m].x,);
- }
- for(;cow[n].y==i;++n){
- br=query_barrier(,,Y,cow[n].x);
- //printf("br(%d)=%d\n",cow[n].x,br);
- ans[cow[n].i]=query_cnt(,,Y,cow[n].x,br);
- //printf("query(%d,%d)=%d\n",cow[n].x,br,ans[cow[n].i]);
- }
- }
- for(int i=;i<n;++i)printf("%d\n",ans[i]);
- }
TA爷的代码
TA爷的模拟赛.....暴力都没写.....有点对不起TA爷....(不过似乎当时这题没得分的?)
自己的代码比较丑,这里附上当时TA爷的std,供参考
【BZOJ-4422】Cow Confinement 线段树 + 扫描线 + 差分 (优化DP)的更多相关文章
- BZOJ 4422 Cow Confinement (线段树、DP、扫描线、差分)
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4422 我真服了..这题我能调一天半,最后还是对拍拍出来的...脑子还是有病啊 题解: ...
- 【Codeforces720D】Slalom 线段树 + 扫描线 (优化DP)
D. Slalom time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...
- 线段树区间合并优化dp——cf1197E(好)
线段树优化dp的常见套路题,就是先按某个参数排序,然后按这个下标建立线段树,再去优化dp 本题由于要维护两个数据:最小值和对应的方案数,所以用线段树区间合并 /* dp[i]表示第i个套娃作为最内层的 ...
- bzoj 2131 : 免费的馅饼 (树状数组优化dp)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2131 思路: 题目给出了每个馅饼的下落时间t,和位置p,以及价值v,我们可以得到如下状态 ...
- [BZOJ 4771]七彩树(可持久化线段树+树上差分)
[BZOJ 4771]七彩树(可持久化线段树+树上差分) 题面 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i] ...
- BZOJ 1818 线段树+扫描线
思路: 可以把题目转化成 给你一些沿坐标轴方向的线段 让你求交点个数 然后就线段树+扫描线 搞一搞 (线段不包含断点 最后+n 这种方式 比线段包含断点+各种特判要好写得多) //By SiriusR ...
- Codeforces VK CUP 2015 D. Closest Equals(线段树+扫描线)
题目链接:http://codeforces.com/contest/522/problem/D 题目大意: 给你一个长度为n的序列,然后有m次查询,每次查询输入一个区间[li,lj],对于每一个查 ...
- 【POJ-2482】Stars in your window 线段树 + 扫描线
Stars in Your Window Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11706 Accepted: ...
- HDU 4419 Colourful Rectangle --离散化+线段树扫描线
题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何 ...
随机推荐
- PHP & Delphi 語法
明 C(区分大小写) Delphi(不区分大小写) PHP(区分大小写) 整型变量的定义 1 2 3 4 5 6 7 char a = 'a'; /* 8位有符号*/ int a=10 ...
- Java核心技术点之反射
1. 概述 Java 反射是可以让我们在运行时获取类的方法.属性.父类.接口等类的内部信息的机制.也就是说,反射本质上是一个“反着来”的过程.我们通过new创建一个类的实例时,实际上是由Java虚拟机 ...
- BZOJ 1834 【ZJOI2010】 network 网络扩容
Description 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不扩容的情况下,1到N的最大流: 2. 将1到N的最大流增加K所需的 ...
- WF4.0 工作流设计器 传入参数问题记录?
在本公司的流程设计器 ,如果流程中使用了传入参数,应先定义 参数,然后再拖动节点,才能正确提交,否则出错,原因未查明,只观察到现象.
- android中按电源键锁屏然后解锁导致Activity调用onDestory以及如何防止锁屏
今天在android项目中按电源键锁屏,然后解锁,发现子Activity关闭了,回到了主页,这个问题困扰了我很久,最后打log发现,在按电源键的时候,调用了子Activity的onDestroy()方 ...
- 异常检测算法--Isolation Forest
南大周志华老师在2010年提出一个异常检测算法Isolation Forest,在工业界很实用,算法效果好,时间效率高,能有效处理高维数据和海量数据,这里对这个算法进行简要总结. iTree 提到森林 ...
- PHP 基础笔记
数据类型 字符串 整数 浮点数 布尔值 数组 对象 NULL 未定义的变量,数据类型为 NULL. PHP 中数组和对象是不同的类型,而 js 中数组即为对象.(ps: es6 已经内置了 class ...
- [【codechefCHSEQ22】Chef and Favourite Sequence(并查集)
题目:http://hzwer.com/3419.html 题意:给你一个全是0的数列,有m种操作[Li,Ri],每次操作就将下标处于[Li,Ri]的元素取反.你可以选若干个操作来使这个数列最后变成别 ...
- C程序中对时间的处理——time库函数详解
包含文件:<sys/time.h> <time.h> 一.在C语言中有time_t, tm, timeval等几种类型的时间 1.time_t time_t实际上是长整数类型, ...
- HFS汉化版|简易HTTP服务器
专为个人用户所设计的 HTTP 档案系统 - Http File Server,如果您觉得架设 FTP Server 太麻烦,那么这个软件可以提供您更方便的档案传输系统,下载后无须安装,只要解压缩后执 ...