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;
}

  

时间: 2024-08-09 23:41:45

BZOJ1120 : [POI2009]STR的相关文章

python判断字符串,str函数isdigit、isdecimal、isnumeric的区别

s为字符串s.isalnum() 所有字符都是数字或者字母s.isalpha() 所有字符都是字母s.isdigit() 所有字符都是数字s.islower() 所有字符都是小写s.isupper() 所有字符都是大写s.istitle() 所有单词都是首字母大写,像标题s.isspace() 所有字符都是空白字符.\t.\n.\r 判断是整数还是浮点数a=123b=123.123 >>>isinstance(a,int)True>>>isinstance(b,floa

int、str、list、tuple、dict补充

一.int a = 123 b = a# a与b指向同一个地址值 c = 123 d = 123 e = 123 #d.c.e当在-5~257这个范围时,都指向一个地址值(Python优化的结果,当超出这个范围,id与之不同) 二.str a. name = "你猜" for i in name: print(i) bytes_name = bytes(i, encoding='utf-8')# 字符转换成字节 print(byte_name)# 16进制表示 for byte in

TypeError: string indices must be integers, not str

1. TypeError: string indices must be integers, not str 字符串类型取第index个字符的时候,应该传入int而不是str.如 view source print? 1 a='abcdef' 2 print a[0] 3 #而不是 print a['0'] 更常见的情况是把一个string当成了字典在使用 :should_be_dict_but_string['id'] .这样的错误

Rust的str与String

字面量 http://doc.rust-lang.org/reference.html#literals 字面量是放在编译后的二进制的静态数据段的. str字面量引用 let a_str = "abcdefg" let b_str = "你好世界"  使用字符串字面量创建的字符串引用,其 lifetime 是 'static 的.而使用另一种方式:来自 String 的形式创建的&str,其 lifetime 是非 'static 的. &str是不

istringstream字符串流,实现类似字符串截取的功能,字符串流中的put,str()将流转换成为字符串string

 1. istringstream字符串流 #include <iostream> #include <sstream> #include <string> using namespace std; struct MyStruct { string str1, str2, str3; double db; int num; char ch; }; void main() { string  mystring("china  google microsoft

PyQt QString 与 Python str&amp;unicode

昨日,将许久以前做的模拟网页登录脚本用PyQt封装了一下,结果出大问题了, 登录无数次都提示登录失败!!而不用PyQt实现的GUI登录直接脚本登录无数次都提示登录成功!!心中甚是伤痛,于是探究起来,解决这一问题. 问题描述及证据如下: 上图是脚本MD5加密过程及结果 上图是PyQt GUI中获取密码框内容后加密的结果,其实现代码如下: # -*- coding: gbk -*- ''' Version : Python27 Author : Spring God Date : 2013-6-28

PYTHON编码处理-str与Unicode的区别

一篇关于str和Unicode的好文章 整理下python编码相关的内容 注意: 以下讨论为Python2.x版本, Py3k的待尝试 开始 用python处理中文时,读取文件或消息,http参数等等 一运行,发现乱码(字符串处理,读写文件,print) 然后,大多数人的做法是,调用encode/decode进行调试,并没有明确思考为何出现乱码 所以调试时最常出现的错误 错误1 Traceback (most recent call last): File "<stdin>"

堆与栈(JAVA)——以String str=&quot;abc&quot;的深度含义解释

栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器.但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性.另外,栈数据在多个线程或者多个栈之间是不可以共享的,但是在栈内部多个值相等的变量是可以指向一个地址的.堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据.但缺点是,由于要在运

python问题:TypeError: a bytes-like object is required, not &#39;str&#39;

源程序: import socket target_host = "www.baidu.com" # 127.0.0.1 target_port = 80 # 建立一个socket对象 client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 创建TCP连接 # 连接客户端 client.connect((target_host,target_port)) client.send("GET / HTTP/1.1\r