Description
GFS打算去郊外建所别墅,享受生活,于是他耗费巨资买下了一块风水宝地,但令他震惊的是,一群DSJ对GFS的富贵生活深恶痛绝,决定打洞以搞破坏。
现在我们简化一下这个问题,在这片土地上会按顺序发生一系列事件。
①一只DSJ在(x,y) 这个点打了一个洞。
②有着高雅品味GFS想建一个等腰直角三角形的别墅,即由(x,y) ,(x+d,y) ,(x,y+d) 三点围成的三角形,但为了地基的牢固,他想知道当前这块三角形土地内的洞的个数。
GFS现在对DSJ已经忍无可忍了,请你帮他回答这些询问。
初始土地上没有洞。GFS毕竟是GFS,你可以认为土地无限大。
Input
第一行一个整数 n,表示事件数。接下来n行,每行3个非负整数x ,y ,d 。
若d=0 表示DSJ打洞的事件。否则表示GFS建房的询问。
Output
对每个询问输出一个整数,表示当时询问的三角形内的洞的个数。
Sample Input
输入1:
8
1 3 0
1 5 0
3 6 0
4 4 0
2 6 0
1 5 3
1 5 4
1 1 1
输入2:
4
1 5 0
3 7 0
2 5 6
2 3 4
Sample Output
输出1:
3
3
0
输出2:
1
0
Data Constraint
30%的数据n<=3333 。
另30% 的数据 GFS只会在DSJ打完洞后才开始询问,xi,yi<=333333 。
100%的数据 1<=n<=88888,xi,yi<=3333333 。
题解
这个是个三维偏序问题,
时间还有二维平面。
这种问题一般是用cdq分治处理掉时间,
然后再二维平面上面用树套树维护。
而这里是要维护一个三角形,并不是常见的四边形。
其实可以把等腰三角形拆开来,拆成一个直角梯形,另一腰围45度,和一个长方形,
于是这样就可以解决了。
code
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#define ll long long
#define N 100003
#define M 103
#define db double
#define P putchar
#define G getchar
using namespace std;
char ch;
void read(int &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
ll w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
n*=w;
}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}
struct node
{
int id,z,x,y,t;
}a[N*2],t[N*2];
bool cmp(node a,node b)
{
return a.y<b.y;
}
int n,ans[N],m,q;
int x[N],y[N],d[N],s[10000003];
int x_(int x){return x&(-x);}
void ins(int x,int z)
{
for(int i=x;i<=m;i=i+x_(i))
s[i]=s[i]+z;
}
int find(int x)
{
int t=0;
for(int i=x;i;i=i-x_(i))
t=t+s[i];
return t;
}
void solve(int l,int r)
{
if(l==r)return;
int mid=(l+r)>>1;
for(int i=l,s1=l,s2=mid+1;i<=r;i++)
if(a[i].x<=mid)t[s1++]=a[i];else t[s2++]=a[i];
for(int i=l;i<=r;i++)a[i]=t[i];
solve(l,mid);
for(int i=l,j=mid+1;j<=r;j++)
{
for(;i<=mid && a[i].y<=a[j].y;i++)
if(a[i].t==0)ins(a[i].z,1);
if(a[j].t)ans[a[j].id]=ans[a[j].id]+find(a[j].z)*a[j].t;
if(j==r)
{
for(;i>l;)
if(a[--i].t==0)ins(a[i].z,-1);
}
}
solve(mid+1,r);
sort(a+l,a+r+1,cmp);
}
int main()
{
read(n);
for(int i=1;i<=n;i++)
read(x[i]),read(y[i]),read(d[i]),m=max(m,x[i]+y[i]+d[i]);
for(int i=1;i<=n;i++)
if(d[i]==0)
{
q++;
a[q].z=x[i]+y[i];
a[q].x=q;
a[q].y=x[i];
a[q].id=i;
a[q].t=0;
}
else
{
q++;
a[q].z=x[i]+y[i]+d[i];
a[q].x=q;
a[q].y=x[i]-1;
a[q].id=i;
a[q].t=-1;
q++;
a[q].z=x[i]+y[i]+d[i];
a[q].x=q;
a[q].y=x[i]+d[i];
a[q].id=i;
a[q].t=1;
}
sort(a+1,a+1+q,cmp);
solve(1,q);
q=0;
for(int i=1;i<=n;i++)
if(d[i]==0)
{
q++;
a[q].z=y[i];
a[q].x=q;
a[q].y=x[i];
a[q].id=i;
a[q].t=0;
}
else
{
q++;
a[q].z=y[i]-1;
a[q].x=q;
a[q].y=x[i]-1;
a[q].id=i;
a[q].t=1;
q++;
a[q].z=y[i]-1;
a[q].x=q;
a[q].y=x[i]+d[i];
a[q].id=i;
a[q].t=-1;
}
sort(a+1,a+1+q,cmp);
solve(1,q);
for(int i=1;i<=n;i++)
if(d[i])write(ans[i]),P('\n');
return 0;
}