BZOJ-3228 棋盘控制 线段树+扫描线+鬼畜毒瘤
3228: [Sdoi2008]棋盘控制
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 23 Solved: 9
[Submit][Status][Discuss]
Description
在一个N * M的棋盘上,摆放着K个棋子,一个棋子占据一个格子(可能有多个棋子占据同一个格子),控制棋盘上所有与它相距不超过R的格子。两个格子(X1,Y1)、(X2,Y2)间的距离定义为|X1-X2|+|Y1-Y2|。
试设计一个算法,计算出K个棋子控制的格子总数。
Input
第一行共三个正整数N,M,K。
以下K行,每行三个正整数X,Y,R,分别表示棋子的所在行,所在列和控制范围。
Output
共一个数,即控制的格子总数。
Sample Input
4 4 3
1 1 1
3 1 1
3 3 1
Sample Output
10
HINT
在 100% 的数据中,1≤N,M≤100000000,1≤K≤100000
Source
线段树+扫描线(一维),鬼畜的处理。。。恶心人
学了发扫描线的姿势。。真恶心。。。
code:(看着就难受)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include <cstdlib>
using namespace std;
#define maxk 300005
long long read()
{
long long x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
long long max(long long a,int b)
{
if (a>b) return a;
return b;
}
struct data{long long x,y,r;}in[maxk];
struct dat{
long long x,y1,y2,k;
bool operator < (const dat & A) const
{
return x<A.x;
}
};
struct da{
long long st,ed;
long long sqr()
{
if ((ed-st+1)&1) return (ed-st+2)*((ed-st+1)/2+1)/2;
else return (ed-st+1+2)*((ed-st+1-2)/2+1)/2;
}
bool operator < (const da A) const
{
return st<A.st;
}
};
int n,m,k;
#define maxn 1200005
struct SegmentTree{
int del[maxn],tree[maxn];
int Y[maxk];
void clear()
{
memset(del,0,sizeof(del));
memset(tree,0,sizeof(tree));
}
void updata(int now,long long l,long long r)
{
if (del[now]>0) tree[now]=r-l;
else tree[now]=tree[now<<1]+tree[now<<1|1];
}
void insert(int now,int l,int r,int L,int R,int num)
{
int mid=(l+r)>>1;
if (L<=Y[l] && R>=Y[r]) del[now]+=num; else
{
if (L<Y[mid]) insert(now<<1,l,mid,L,R,num);
if (R>Y[mid]) insert(now<<1|1,mid,r,L,R,num);
}
updata(now,Y[l],Y[r]);
}
long long query()
{
return tree[1];
}
}T;
struct cal{
dat line[maxk];
int tot,n;
long long x1[maxk],x2[maxk],y1[maxk],y2[maxk];
long long calc()
{
T.clear();
for (int i=1; i<=n; i++) T.Y[i*2-1]=y1[i],T.Y[i*2]=y2[i];
sort(T.Y+1,T.Y+2*n+1); tot=1;
for (int i=2; i<=2*n; i++) if (T.Y[i]!=T.Y[i-1]) T.Y[++tot]=T.Y[i];
for (int i=1; i<=n; i++)
{
line[i*2-1].x=x1[i]; line[i*2-1].y1=y1[i]; line[i*2-1].y2=y2[i];
line[i*2].x=x2[i]; line[i*2].y1=y1[i]; line[i*2].y2=y2[i];
line[i*2-1].k=1; line[i*2].k=-1;
}
sort(line+1,line+2*n+1);
long long ans=0,last=0;
for (int i=1; i<=2*n; i++)
{
if (i!=1) ans=ans+last*(long long)((long long)(line[i].x)-(long long)line[i - 1].x);
if (last<0) {int a;a+=1;}
if (line[i].y1!=line[i].y2) T.insert(1,1,tot,line[i].y1,line[i].y2,line[i].k);
last=T.query();
}
return ans;
}
}calc1, calc2;
struct calcc{
int n;
da tri[maxk],tmp;
long long cal()
{
if (n==0) return 0ll;
long long ans=0; da tmp;
sort(tri+1,tri+n+1);
ans=tri[1].sqr(); int now=1;
for (int i=2; i<=n; i++)
{
if (tri[i].st>=tri[now].st && tri[i].ed<=tri[now].ed) continue;
if (tri[i].st>tri[now].ed)
{
ans+=tri[i].sqr(); now=i; continue;
}
ans+=tri[i].sqr();tmp.st=tri[i].st; tmp.ed=tri[now].ed;
ans-=tmp.sqr(); now=i;
}
return ans;
}
}tc[5];
int main()
{
n=read(),m=read(),k=read();
for (int i=1; i<=k; i++) in[i].x=read(),in[i].y=read(),in[i].r=read();
calc1.n=calc2.n=k;
for (int i=1; i<=k; i++)
{
int tmp=in[i].r-((in[i].x+in[i].y+in[i].r)&1);
calc1.x1[i]=(in[i].x+in[i].y-tmp)>>1;
calc1.y1[i]=(in[i].y-tmp-in[i].x)>>1;
calc1.x2[i]=((in[i].x+in[i].y+ tmp)>>1)+1;
calc1.y2[i]=((in[i].y+tmp-in[i].x)>>1)+1;
}
for (int i=1; i<=k; i++)
{
int tmp=in[i].r-(!((in[i].x+in[i].y+in[i].r)&1));
calc2.x1[i]=(in[i].x+in[i].y-tmp-1)>>1;
calc2.y1[i]=(in[i].y-tmp-in[i].x-1)>>1;
calc2.x2[i]=((in[i].x+in[i].y+tmp-1)>>1)+1;
calc2.y2[i]=((in[i].y+tmp-in[i].x-1)>>1)+1;
}
long long ans=0;
ans=calc1.calc()+calc2.calc();
for (int i=1; i<=k; i++) if (in[i].r>=in[i].x)
{
++tc[1].n;
tc[1].tri[tc[1].n].st=in[i].y-(in[i].r-in[i].x);
tc[1].tri[tc[1].n].ed=in[i].y+(in[i].r-in[i].x);
}
for (int i=1; i<=k; i++) if (in[i].r>=in[i].y)
{
++tc[2].n;
tc[2].tri[tc[2].n].st=in[i].x-(in[i].r-in[i].y);
tc[2].tri[tc[2].n].ed=in[i].x+(in[i].r-in[i].y);
}
for (int i=1; i<=k; i++) if (in[i].r>=n+1-in[i].x)
{
++tc[3].n;
tc[3].tri[tc[3].n].st=in[i].y-(in[i].r-(n+1-in[i].x));
tc[3].tri[tc[3].n].ed=in[i].y+(in[i].r-(n+1-in[i].x));
}
for (int i=1; i<=k; i++) if (in[i].r>=m+1-in[i].y)
{
++tc[4].n;
tc[4].tri[tc[4].n].st=in[i].x-(in[i].r-(m+1-in[i].y));
tc[4].tri[tc[4].n].ed=in[i].x+(in[i].r-(m+1-in[i].y));
}
for (int i=1; i<=4; i++)
ans-=tc[i].cal();
long long m1=0,m2=0,m3=0,m4=0;
for (int i=1; i<=k; i++)
{
if (in[i].r>=in[i].x+in[i].y) m1=max(m1,1+in[i].r-in[i].x-in[i].y);
if (in[i].r>=in[i].x+(m+1-in[i].y)) m2=max(m2, 1+in[i].r-in[i].x-(m+1-in[i].y));
if (in[i].r>=in[i].y+(n+1-in[i].x)) m3=max(m3, 1+in[i].r-in[i].y-(n+1-in[i].x));
if (in[i].r>=(m+1-in[i].y)+(n+1-in[i].x)) m4=max(m4,1+in[i].r-((m+1-in[i].y)+(n+1-in[i].x)));
}
ans+=m1*(m1+1)/2+m2*(m2+1)/2+m3*(m3+1)/2+m4*(m4+1)/2;
printf("%lld\n",ans);
return 0;
}
BZOJ-3228 棋盘控制 线段树+扫描线+鬼畜毒瘤的更多相关文章
- BZOJ 1818 线段树+扫描线
思路: 可以把题目转化成 给你一些沿坐标轴方向的线段 让你求交点个数 然后就线段树+扫描线 搞一搞 (线段不包含断点 最后+n 这种方式 比线段包含断点+各种特判要好写得多) //By SiriusR ...
- BZOJ 4422 Cow Confinement (线段树、DP、扫描线、差分)
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4422 我真服了..这题我能调一天半,最后还是对拍拍出来的...脑子还是有病啊 题解: ...
- BZOJ-3225 立方体覆盖 线段树+扫描线+乱搞
看数据范围像是个暴力,而且理论复杂度似乎可行,然后被卡了两个点...然后来了个乱搞的线段树+扫描线.. 3225: [Sdoi2008]立方体覆盖 Time Limit: 2 Sec Memory L ...
- 【Codeforces720D】Slalom 线段树 + 扫描线 (优化DP)
D. Slalom time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...
- 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种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何 ...
- hdu 5091(线段树+扫描线)
上海邀请赛的一道题目,看比赛时很多队伍水过去了,当时还想了好久却没有发现这题有什么水题的性质,原来是道成题. 最近学习了下线段树扫描线才发现确实是挺水的一道题. hdu5091 #include &l ...
- POJ1151+线段树+扫描线
/* 线段树+扫描线+离散化 求多个矩形的面积 */ #include<stdio.h> #include<string.h> #include<stdlib.h> ...
随机推荐
- Android系列之Fragment(三)----Fragment和Activity之间的通信(含接口回调)
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
- 利用OpacityMask制作打洞效果
起因 项目上存在一个连线功能,在设计的原型中,在连线中间文字上下各有15像素的空白.接手的同事觉得没思路,问我能不能在不影响连线后面的背景情况下解决该问题.我就抽了点时间给他写了个Demo.回家后趁热 ...
- flex+AS3编程规范
flex+AS3编程规范 Flex+AS3编码规范 http://www.cnblogs.com/jiahuafu/ 1. 缩写: 尽量避免使用缩写,使用缩写时尽量和Flex保持一致.但要记住一 ...
- java 15 - 6 List的方法
List集合的特有功能: A:添加功能 void add(int index,Object element):在指定索引处添加元素 B:获取功能 Object get(int index):获取指定索 ...
- Maya FEM节点框架完成
这几天把物理模拟框架移植到maya之中了. maya编程有一点比较关键,就是要让自己的程序逻辑适应maya的节点求值机制.在物理模拟中,往往需要进行时间积分,对此我的解决办法是,写一个节点rigSim ...
- vrrp两用
早上想了想vrrp的使用,1,网关冗余 2,服务器热备 思想稍微有点不一样.主要在于监控口 服务器的话有心跳线,用户同步一些配置和迁移一些服务.达到热备的目的.:牵涉到四个优先级:建议这样排序: 主机 ...
- Objective-c归档的概念和用法
‘
- Google protocol buffer在windows下的编译
在caffe框架中,使用的数据格式是google的 protocol buffer.对这个不了解,所以,想简单学习一下.简单来说,Protocol Buffer 是一种轻便高效的结构化数据存储格式,可 ...
- Ubuntu 16.04 LTS安装好需要设置的15件事(喜欢新版本)
看到这篇文章说明你已经从老版本升级到 Ubuntu 16.04 或进行了全新安装,在安装好 Ubuntu 16.04 LTS 之后建议大家先做如下 15 件事.无论你是刚加入 Ubuntu 行列的新用 ...
- Java 环境下使用 AES 加密的特殊问题处理
在 Java 环境下使用 AES 加密,在密钥长度和字节填充方面有一些比较特殊的处理. 1. 密钥长度问题 默认 Java 中仅支持 128 位密钥,当使用 256 位密钥的时候,会报告密钥长度错误 ...