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 棋盘控制 线段树+扫描线+鬼畜毒瘤的更多相关文章

  1. BZOJ 1818 线段树+扫描线

    思路: 可以把题目转化成 给你一些沿坐标轴方向的线段 让你求交点个数 然后就线段树+扫描线 搞一搞 (线段不包含断点 最后+n 这种方式 比线段包含断点+各种特判要好写得多) //By SiriusR ...

  2. BZOJ 4422 Cow Confinement (线段树、DP、扫描线、差分)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4422 我真服了..这题我能调一天半,最后还是对拍拍出来的...脑子还是有病啊 题解: ...

  3. BZOJ-3225 立方体覆盖 线段树+扫描线+乱搞

    看数据范围像是个暴力,而且理论复杂度似乎可行,然后被卡了两个点...然后来了个乱搞的线段树+扫描线.. 3225: [Sdoi2008]立方体覆盖 Time Limit: 2 Sec Memory L ...

  4. 【Codeforces720D】Slalom 线段树 + 扫描线 (优化DP)

    D. Slalom time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...

  5. Codeforces VK CUP 2015 D. Closest Equals(线段树+扫描线)

    题目链接:http://codeforces.com/contest/522/problem/D 题目大意:  给你一个长度为n的序列,然后有m次查询,每次查询输入一个区间[li,lj],对于每一个查 ...

  6. 【POJ-2482】Stars in your window 线段树 + 扫描线

    Stars in Your Window Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11706   Accepted:  ...

  7. HDU 4419 Colourful Rectangle --离散化+线段树扫描线

    题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何 ...

  8. hdu 5091(线段树+扫描线)

    上海邀请赛的一道题目,看比赛时很多队伍水过去了,当时还想了好久却没有发现这题有什么水题的性质,原来是道成题. 最近学习了下线段树扫描线才发现确实是挺水的一道题. hdu5091 #include &l ...

  9. POJ1151+线段树+扫描线

    /* 线段树+扫描线+离散化 求多个矩形的面积 */ #include<stdio.h> #include<string.h> #include<stdlib.h> ...

随机推荐

  1. Android系列之Fragment(三)----Fragment和Activity之间的通信(含接口回调)

    ​[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...

  2. 利用OpacityMask制作打洞效果

    起因 项目上存在一个连线功能,在设计的原型中,在连线中间文字上下各有15像素的空白.接手的同事觉得没思路,问我能不能在不影响连线后面的背景情况下解决该问题.我就抽了点时间给他写了个Demo.回家后趁热 ...

  3. flex+AS3编程规范

    flex+AS3编程规范 Flex+AS3编码规范 http://www.cnblogs.com/jiahuafu/   1.  缩写: 尽量避免使用缩写,使用缩写时尽量和Flex保持一致.但要记住一 ...

  4. java 15 - 6 List的方法

    List集合的特有功能: A:添加功能 void add(int index,Object element):在指定索引处添加元素 B:获取功能 Object get(int index):获取指定索 ...

  5. Maya FEM节点框架完成

    这几天把物理模拟框架移植到maya之中了. maya编程有一点比较关键,就是要让自己的程序逻辑适应maya的节点求值机制.在物理模拟中,往往需要进行时间积分,对此我的解决办法是,写一个节点rigSim ...

  6. vrrp两用

    早上想了想vrrp的使用,1,网关冗余 2,服务器热备 思想稍微有点不一样.主要在于监控口 服务器的话有心跳线,用户同步一些配置和迁移一些服务.达到热备的目的.:牵涉到四个优先级:建议这样排序: 主机 ...

  7. Objective-c归档的概念和用法

  8. Google protocol buffer在windows下的编译

    在caffe框架中,使用的数据格式是google的 protocol buffer.对这个不了解,所以,想简单学习一下.简单来说,Protocol Buffer 是一种轻便高效的结构化数据存储格式,可 ...

  9. Ubuntu 16.04 LTS安装好需要设置的15件事(喜欢新版本)

    看到这篇文章说明你已经从老版本升级到 Ubuntu 16.04 或进行了全新安装,在安装好 Ubuntu 16.04 LTS 之后建议大家先做如下 15 件事.无论你是刚加入 Ubuntu 行列的新用 ...

  10. Java 环境下使用 AES 加密的特殊问题处理

    在 Java 环境下使用 AES 加密,在密钥长度和字节填充方面有一些比较特殊的处理. 1. 密钥长度问题 默认 Java 中仅支持 128 位密钥,当使用 256 位密钥的时候,会报告密钥长度错误 ...