BZOJ1120 : [POI2009]STR
因为问题的对称性,只需要考虑求出有多少点离$A$更近即可。
枚举$4$个绝对值的正负号,可以解出坐标范围。
若可以转化为二维数点,则可以统一扫描线+树状数组解决。
否则是三维数点,按一维排序,剩下两维维护KD-Tree即可。
时间复杂度$O(n\sqrt{n})$。
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=100010;
int W,H,n,m,i,j,A,B,C,D,X,Y,ans[N*2];
struct P{int x,y;}a[N];
inline bool cmpx(const P&a,const P&b){return a.x<b.x;}
inline bool cmpXY(int x,int y){return X*a[x].x+Y*a[x].y<X*a[y].x+Y*a[y].y;}
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline void umin(int&a,int b){if(a>b)a=b;}
inline void umax(int&a,int b){if(a<b)a=b;}
namespace RangeQuery{
struct E{
int x,l,r,t;
E(){}
E(int _x,int _l,int _r,int _t){x=_x,l=_l,r=_r,t=_t;}
}e[N*20];
int cnt,v[N],bit[N];
inline bool cmp(const E&a,const E&b){return a.x<b.x;}
inline void addquery(int xl,int xr,int yl,int yr,int o){
e[++cnt]=E(xr,yl,yr,o);
e[++cnt]=E(xl-1,yl,yr,-o);
}
inline int getl(int x){
int l=1,r=n,mid,t=n+1;
while(l<=r)if(v[mid=(l+r)>>1]>=x)r=(t=mid)-1;else l=mid+1;
return t;
}
inline int getr(int x){
int l=1,r=n,mid,t=0;
while(l<=r)if(v[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
return t;
}
inline void add(int x){for(;x<=n;x+=x&-x)bit[x]++;}
inline int ask(int x){int t=0;for(;x;x-=x&-x)t+=bit[x];return t;}
void solve(){
sort(e+1,e+cnt+1,cmp);
for(i=1;i<=n;i++)v[i]=a[i].y;
sort(v+1,v+n+1);
sort(a+1,a+n+1,cmpx);
for(i=j=1;i<=cnt;i++){
while(j<=n&&a[j].x<=e[i].x)add(getl(a[j++].y));
int l=getl(e[i].l),r=getr(e[i].r);
if(l>r)continue;
int t=ask(r)-ask(l-1);
if(e[i].t>0)ans[e[i].t]+=t;else ans[-e[i].t]-=t;
}
}
}
namespace KDTree{
int q[N],id[N],root,cmp_d,cnt,ret;
struct node{int d[2],l,r,Max[2],Min[2],val,sum,f;}t[N];
inline bool cmp(const node&a,const node&b){return a.d[cmp_d]<b.d[cmp_d];}
struct E{
int A,B,C,xl,xr,yl,yr,o;
E(){}
E(int _A,int _B,int _C,int _xl,int _xr,int _yl,int _yr,int _o){
A=_A,B=_B,C=_C,o=_o;
xl=_xl,xr=_xr,yl=_yl,yr=_yr;
}
}e[N*2];
inline bool cmpE(const E&a,const E&b){return a.C<b.C;}
inline void up(int x){
if(t[x].l){
umax(t[x].Max[0],t[t[x].l].Max[0]);
umin(t[x].Min[0],t[t[x].l].Min[0]);
umax(t[x].Max[1],t[t[x].l].Max[1]);
umin(t[x].Min[1],t[t[x].l].Min[1]);
}
if(t[x].r){
umax(t[x].Max[0],t[t[x].r].Max[0]);
umin(t[x].Min[0],t[t[x].r].Min[0]);
umax(t[x].Max[1],t[t[x].r].Max[1]);
umin(t[x].Min[1],t[t[x].r].Min[1]);
}
}
int build(int l,int r,int D,int f){
int mid=(l+r)>>1;
cmp_d=D;nth_element(t+l+1,t+mid+1,t+r+1,cmp);
id[t[mid].f]=mid;
t[mid].f=f;
t[mid].Max[0]=t[mid].Min[0]=t[mid].d[0];
t[mid].Max[1]=t[mid].Min[1]=t[mid].d[1];
if(l!=mid)t[mid].l=build(l,mid-1,!D,mid);
if(r!=mid)t[mid].r=build(mid+1,r,!D,mid);
return up(mid),mid;
}
void init(){
for(i=1;i<=n;i++)t[i].d[0]=a[i].x,t[i].d[1]=a[i].y,t[i].f=i;
root=build(1,n,0,0);
sort(e+1,e+cnt+1,cmpE);
}
inline void addquery(int A,int B,int C,int xl,int xr,int yl,int yr,int o){
e[++cnt]=E(A,B,C,xl,xr,yl,yr,o);
}
inline void change(int x){for(t[x].val=1;x;x=t[x].f)t[x].sum++;}
void ask(int x){
if(!t[x].sum||t[x].Max[0]<A||t[x].Min[0]>B||t[x].Max[1]<C||t[x].Min[1]>D)return;
if(t[x].Min[0]>=A&&t[x].Max[0]<=B&&t[x].Min[1]>=C&&t[x].Max[1]<=D){ret+=t[x].sum;return;}
if(t[x].val&&t[x].d[0]>=A&&t[x].d[0]<=B&&t[x].d[1]>=C&&t[x].d[1]<=D)ret++;
if(t[x].l)ask(t[x].l);
if(t[x].r)ask(t[x].r);
}
void solve(int _X,int _Y){
X=_X,Y=_Y;
for(i=1;i<=n;i++)t[i].val=t[i].sum=0;
for(i=1;i<=n;i++)q[i]=i;
sort(q+1,q+n+1,cmpXY);
for(i=j=1;i<=cnt;i++)if(e[i].A==X&&e[i].B==Y){
while(j<=n&&X*a[q[j]].x+Y*a[q[j]].y<e[i].C)change(id[q[j++]]);
ret=0;
A=e[i].xl,B=e[i].xr,C=e[i].yl,D=e[i].yr;
ask(root);
ans[e[i].o]+=ret;
}
}
}
inline void deal(int A,int B,int C,int D,int o){
for(int S=0;S<16;S++){
ll c=0;int a=0,b=0,xl=1,xr=W,yl=1,yr=H;
if(S&1)a++,c-=A,umax(xl,A);else a--,c+=A,umin(xr,A-1);
if(S&2)b++,c-=B,umax(yl,B);else b--,c+=B,umin(yr,B-1);
if(S&4)a--,c+=C,umax(xl,C);else a++,c-=C,umin(xr,C-1);
if(S&8)b--,c+=D,umax(yl,D);else b++,c-=D,umin(yr,D-1);
if(xl>xr||yl>yr)continue;
if(!a&&!b&&c>=0)continue;
if(a||b){
a/=2,b/=2;
if(c%2==0||c>0)c/=2;else c=c/2-1;
}
int _c=c;
if(a<0&&!b)umax(xl,_c+1);
if(a>0&&!b)umin(xr,-_c-1);
if(b<0&&!a)umax(yl,_c+1);
if(b>0&&!a)umin(yr,-_c-1);
if(xl>xr||yl>yr)continue;
if(!a||!b)RangeQuery::addquery(xl,xr,yl,yr,o);
else KDTree::addquery(a,b,-c,xl,xr,yl,yr,o);
}
}
int main(){
read(W),read(H),read(n),read(m);
for(i=1;i<=n;i++)read(a[i].x),read(a[i].y);
for(i=1;i<=m;i++){
read(A),read(B),read(C),read(D);
deal(A,B,C,D,i*2-1);
deal(C,D,A,B,i*2);
}
RangeQuery::solve();
KDTree::init();
KDTree::solve(-1,-1);
KDTree::solve(-1,1);
KDTree::solve(1,-1);
KDTree::solve(1,1);
for(i=1;i<=m;i++)printf("%d %d %d\n",ans[i*2-1],ans[i*2],n-ans[i*2-1]-ans[i*2]);
return 0;
}
BZOJ1120 : [POI2009]STR的更多相关文章
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- [转]Python中的str与unicode处理方法
早上被python的编码搞得抓耳挠腮,在搜资料的时候感觉这篇博文很不错,所以收藏在此. python2.x中处理中文,是一件头疼的事情.网上写这方面的文章,测次不齐,而且都会有点错误,所以在这里打算自 ...
- python中的str,unicode和gb2312
实例1: v1=u '好神奇的问题!?' type(v1)->unicode v1.decode("utf-8")# not work,because v1 is unico ...
- LDR、STR指令
LDR(load register)指令将内存内容加载入通用寄存器 STR(store register)指令将寄存器内容存入内存空间中 #define GPJ0CON 0xE0200240 _sta ...
- Python之str()与repr()的区别
Python之str()与repr()的区别 str()一般是将数值转成字符串,主要面向用户. repr()是将一个对象转成字符串显示,注意只是显示用,有些对象转成字符串没有直接的意思.如list, ...
- 判断一个字符串str不为空的方法
1.str == null; 2."".equals(str); 3.str.length 4.str.isEmpty(); 注意:length是属性,一般集合类对象拥有的属性,取 ...
- python 3.5: TypeError: a bytes-like object is required, not 'str'
出现该错误往往是通过open()函数打开文本文件时,使用了'rb'属性,如:fileHandle=open(filename,'rb'),则此时是通过二进制方式打开文件的,所以在后面处理时如果使用了s ...
- django 在字符串[str(list)]中精确查找
1.问题描述 1.1表结构 1.2问题 ref_list为id列表的字符串,需要从ref_list中找出包含指定id的数据(eg id=8).如果实用models.objects.filter(ref ...
- Python基本数据类型——str
字符串常用操作 移除空白 分割 长度 索引 切片 class str(basestring): """ str(object='') -> string Retur ...
随机推荐
- Sql Server中查询今天、昨天、本周、上周、本月、上月数据
Sql Server中查询今天.昨天.本周.上周.本月.上月数据 在做Sql Server开发的时候有时需要获取表中今天.昨天.本周.上周.本月.上月等数据,这时候就需要使用DATEDIFF()函数及 ...
- 适配ios9出现的问题:-canOpenURL: failed for URL
-canOpenURL: failed for URL: "wtloginmqq2://qzapp" - error: "(null)" 2015-09-13 ...
- C#高级编程笔记2016年10月12日 运算符重载
1.运算符重载:运算符重重载的关键是在对象上不能总是只调用方法或属性,有时还需要做一些其他工作,例如,对数值进行相加.相乘或逻辑操作等.例如,语句if(a==b).对于类,这个语句在默认状态下会比较引 ...
- 耿丹CS16-2班助教总结
Deadline: 2016-1-7 11:59pm 开篇有言 --又是一年末,不似风光,却添风霜,顶霾前进,踽踽独行,可乎? 助教那些事儿 助教这份工作是之前就担任过的,很羞愧,当时才担任了几天就撒 ...
- 项目管理的一些Tip
最近带领了一个大概150人天的项目,做一些备注: 1, 知人善用. 排期分任务的时候,要先了解每个团队成员的特点,包括技术水平.性格,看他是适合做技术难度大的模块还是适合做业务逻辑复杂的模块. 2, ...
- 上个项目的一些反思 III
离线缓存 之前的项目因为实时性要求比较高,所以一打开客户端,就开始做网络请求.现在想想,是没有做内容的离线缓存.这个问题,我没意识到.产品经理也没有意识到... 我觉得Archiver,来做比较合适, ...
- LRU LFU FIFO 转载
-------------------------------------->href--------------------------> http://blog.chinaunix.n ...
- firefox插件HTTP-Tool的使用方法
2016年11月3日 14:32:01 星期四 chrome 有postman很强大 我比较懒, 不想FQ, 经常用firefox, 试了几款模拟post请求的插件, 觉得http-tool挺简洁的 ...
- 设计模式--适配器模式Adapter(结构型)
一.适配器模式 适配器模式的主要作用是在新接口和老接口之间进行适配.将一个类的接口转换成客户端期望的另外一个接口.其实适配器模式有点无赖之举,在前期设计的时候,我们就不应该考虑适配器模式,而应该通过重 ...
- strsep和strtok_r替代strtok
char *strtok(char *str, const char *delim) 会修改数据源.外部加锁才线程安全(strtok执行结束再解锁执行另一个strtok循环知道工作完成) 主要是以互斥 ...