总体思路 按X,Y排序,线段树按时间维护内最接近的点
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <cstdio>
#include <map>
#include <vector>
#include <list>
#include <functional>
#include <stack>
#include <unordered_map>
#include <set>
#include <cctype>
#include <cstring>
#include <bitset>
#define m(a,b) make_pair(a,b)
#define F first
#define S second
#define ll long long
#define ull unsigned long long
#define us unsigned short
#define MAX(a,b) (a>b?a:b)
#define MIN(a,b) (a<b?a:b)
using namespace std;
const int N=200010,M=1e9*2;
int nt,n;
const pair<int,int> EMPTY=m(M,M);
struct aa
{
pair<int,int> a,f;//a为这个点,f为目标点
int st,et;//开始和结束时间
char op;
} a[N];
aa *b[N],*bb[N];
struct node//线段树
{
pair<int,int> change;
int l,r,mid;
bool empty;
} ste[N*4];
void rebuild(int i,int l,int r)
{
ste[i].l=l;
ste[i].r=r;
ste[i].mid=(l+r)>>1;
ste[i].change=EMPTY;
ste[i].empty=0;
if(l!=r)
{
rebuild(i<<1,l,ste[i].mid);
rebuild((i<<1)+1,ste[i].mid+1,r);
}
}
void spread(int &i)
{
node &z1=ste[i<<1],&z2=ste[(i<<1)+1];
if(ste[i].empty)
{
z1.change=z2.change=EMPTY;
z1.empty=z2.empty=1;
ste[i].empty=0;
}
else if(ste[i].change!=EMPTY)
{
z2.change=z1.change=ste[i].change;
z2.empty=z1.empty=0;
ste[i].change=EMPTY;
}
}
void change(int i,int &l,int &r,pair<int,int> &x)
{
if(ste[i].r<l||ste[i].l>r)
return ;
if(ste[i].l>=l&&ste[i].r<=r)
{
ste[i].change=x;
ste[i].empty=0;
}
else
{
spread(i);
change((i<<1),l,r,x);
change((i<<1)+1,l,r,x);
}
}
pair<int,int> ask(int i,int &k)
{
if(ste[i].l==ste[i].r)
return ste[i].change;
if(ste[i].empty)
return EMPTY;
if(ste[i].change!=EMPTY)
return ste[i].change;
if(k>ste[i].mid)
return ask((i<<1)+1,k);
else
return ask((i<<1),k);
}
bool cmpx(aa* &ai,aa* &bi)
{
if(ai->a.first==bi->a.first)
{
if(ai->a.second==bi->a.second)
return ai->op=='a';
else
return ai->a.second>bi->a.second;
}
else
return ai->a.F>bi->a.F;
}
bool cmpy(aa* &ai,aa* &bi)
{
if(ai->a.S==bi->a.S)
{
if(ai->a.F==bi->a.F)
return ai->op=='a';
else
return ai->a.first>bi->a.first;
}
else
return ai->a.S>bi->a.S;
}
bool cmpt(aa &a,aa &b)
{
return a.st<b.st;
}
struct ct//时间哈希
{
int t,i;
bool s;
} bt[N];
bool cmpbt(ct &a,ct &b)
{
return a.t<b.t;
}
int j[N];
int ji(int x)//记忆化搜索出发子树
{
if(!j[x])
{
int i=1;
while(ste[i].mid>=x)
i<<=1;
j[x]=i;
}
return j[x];
}
void fen(const int l,const int r)
{
if(l==r)
return ;
int mid=(l+r)>>1,lt=1;
for(int i=l;i<=r;i++)//时间哈希
{
bb[i]=b[i];
bt[lt].s=1;
bt[lt].i=i;
bt[lt++].t=b[i]->st;
if(b[i]->et!=nt)
{
bt[lt].s=0;
bt[lt].i=i;
bt[lt++].t=b[i]->et;
}
}
int bsi=ji(lt);
ste[bsi].empty=1;
ste[bsi].change=EMPTY;
sort(bt+1,bt+lt,cmpbt);
for(int i=1;i<lt;i++)//时间哈希修改
{
if(bt[i].s)
bb[bt[i].i]->st=i;
else
bb[bt[i].i]->et=i;
}
sort(bb+l,bb+mid+1,cmpx);
sort(bb+mid+1,bb+r+1,cmpx);
int x=l,y=mid+1;
pair<int,int> cf;
while(y<=r&&x<=mid)//双指针线段树
{
if(bb[x]->a.first>=bb[y]->a.first)
{
if(bb[x]->op=='a')
change(bsi,bb[x]->st,bb[x]->et,bb[x]->a);
x++;
}
else
{
if(bb[y]->op=='f')
{
cf=ask(bsi,bb[y]->st);
if(cf.F<bb[y]->f.F||(cf.F==bb[y]->f.F&&cf.S<bb[y]->f.S))
bb[y]->f=cf;
}
y++;
}
}
while(y<=r)
{
if(bb[y]->op=='f')
{
cf=ask(bsi,bb[y]->st);
if(cf.F<bb[y]->f.F||(cf.F==bb[y]->f.F&&cf.S<bb[y]->f.S))
bb[y]->f=cf;
}
y++;
}
for(int i=1;i<lt;i++)//时间哈希改回
{
if(bt[i].s)
b[bt[i].i]->st=bt[i].t;
else
b[bt[i].i]->et=bt[i].t;
}
fen(l,mid);
fen(mid+1,r);
}
ull zll(pair<int,int> &x)
{
return (ll)x.F*M+x.S;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out1.txt","w",stdout);
unordered_map <ull,int> m;
int t=1;
ull c1;
cin>>n;
nt=n+3;
getchar();
for(int i=1;i<=n;i++)
{
a[i].op=getchar();
switch(a[i].op)
{
case 'r':
getchar(),getchar();
case 'f':
getchar();
case 'a':
getchar(),getchar(),getchar();
}
scanf("%d%d",&a[i].a.first,&a[i].a.second),getchar();
a[i].f=EMPTY;
a[i].et=nt;
a[i].st=t;
if(a[i].op=='a')//记录点
m[zll(a[i].a)]=i;
else if(a[i].op=='r')//找前一个点并修改结束时间
{
c1=zll(a[i].a);
a[m[c1]].et=t;
m.erase(m.find(c1));
a[i]={};
i--;
n--;
}
else
{
a[i].a.first++;
a[i].a.second++;
}
t++;
}
rebuild(1,1,nt);
for(int i=1;i<=n;i++)
b[i]=a+i;
sort(b+1,b+n+1,cmpy);//用指针希望快一点
fen(1,n);//CDQ
for(int i=1;i<=n;++i)
{
if(a[i].op=='f')
{
if(a[i].f!=EMPTY)
printf("%d %d\n",a[i].f.F,a[i].f.S);
else
putchar('-'),putchar('1'),putchar('\n');
}
}
return 0;
}
抽象程序tle18 想尽力减少复杂度结果还不如不改
#include <iostream>//注释与上面程序类似(不想打了qwq)
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <cstdio>
#include <map>
#include <vector>
#include <list>
#include <functional>
#include <stack>
#include <unordered_map>
#include <set>
#include <cctype>
#include <cstring>
#include <bitset>
#define m(a,b) make_pair(a,b)
#define F first
#define S second
#define ll long long
#define ull unsigned long long
#define us unsigned short
#define MAX(a,b) (a>b?a:b)
#define MIN(a,b) (a<b?a:b)
using namespace std;
const int N=200005,M=1e9*2;
int yi=1,nt,n;
const pair<int,int> EMPTY=m(M,M);
struct aa
{
pair<int,int> a,f;
int st,et;
char op;
} a[N];
aa *b[N],*bb[N];
struct node
{
pair<int,int> a,change;
int l,r,mid;
bool empty;
} ste[N*4];
void rebuild(int i,int l,int r)
{
node &p=ste[i];
p.l=l;
p.r=r;
p.mid=(l+r)>>1;
p.a=p.change=EMPTY;
if(l!=r)
{
rebuild(i*2,l,p.mid);
rebuild(i*2+1,p.mid+1,r);
}
}
void change(int i,int &l,int &r,pair<int,int> x);
void spread(int i)
{
node &p=ste[i],&z1=ste[i*2],&z2=ste[i*2+1];
if(p.empty)
{
z1.a=z2.a=z1.change=z2.change=EMPTY;
z1.empty=z2.empty=1;
p.empty=0;
}
else if(p.change!=EMPTY)
{
z2.a=z2.change=z1.a=z1.change=p.change;
p.change=EMPTY;
}
}
void change(int i,int &l,int &r,pair<int,int> x)
{
node &p=ste[i],&z1=ste[i*2],&z2=ste[i*2+1];
if(p.r<l||p.l>r)
return ;
if(p.l>=l&&p.r<=r)
{
p.a=p.change=x;
p.empty=0;
}
else
{
spread(i);
change(i*2,l,r,x);
change(i*2+1,l,r,x);
if(z1.a==z2.a)
p.a=z1.a;
else
p.a=EMPTY;
}
}
pair<int,int> ask(int i,int &k)
{
if(ste[i].l==ste[i].r)
return ste[i].a;
if(ste[i].empty)
return EMPTY;
if(ste[i].a!=EMPTY)
return ste[i].a;
if(k>ste[i].mid)
return ask(i*2+1,k);
else
return ask(i*2,k);
}
bool cmpx(aa* &ai,aa* &bi)
{
if(ai->a.first==bi->a.first)
{
if(ai->a.second==bi->a.second)
return ai->op=='a';
else
return ai->a.second>bi->a.second;
}
else
return ai->a.F>bi->a.F;
}
bool cmpy(aa* &ai,aa* &bi)
{
if(ai->a.S==bi->a.S)
{
if(ai->a.F==bi->a.F)
return ai->op=='a';
else
return ai->a.first>bi->a.first;
}
else
return ai->a.S>bi->a.S;
}
bool cmpt(aa &a,aa &b)
{
return a.st<b.st;
}
void fen(const int l,const int r)
{
if(l==r)
return ;
int mid=(l+r)>>1;
//memcpy(bb+l,b+l,(r-l+1)*8);
for(int i=l;i<=r;i++)
bb[i]=b[i];
sort(bb+l,bb+mid+1,cmpx);
sort(bb+mid+1,bb+r+1,cmpx);
int x=l,y=mid+1;
pair<int,int> cf;
while(y<=r&&x<=mid)
{
if(bb[x]->a.first>=bb[y]->a.first)
{
if(bb[x]->op=='a')
change(1,bb[x]->st,bb[x]->et,bb[x]->a);
x++;
}
else
{
if(bb[y]->op=='f')
{
cf=ask(1,bb[y]->st);
if(cf.F<bb[y]->f.F||(cf.F==bb[y]->f.F&&cf.S<bb[y]->f.S))
bb[y]->f=cf;
}
y++;
}
}
while(y<=r)
{
if(bb[y]->op=='f')
{
cf=ask(1,bb[y]->st);
if(cf.F<bb[y]->f.F||(cf.F==bb[y]->f.F&&cf.S<bb[y]->f.S))
bb[y]->f=cf;
}
y++;
}
ste[1].empty=1;
ste[1].a=ste[1].change=EMPTY;
fen(l,mid);
fen(mid+1,r);
}
ull zll(pair<int,int> &x)
{
return (ll)x.F*M+x.S;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out1.txt","w",stdout);
unordered_map <ull,int> m;
int t=1;
ull c1;
cin>>n;
nt=n+3;
rebuild(1,1,n);
getchar();
for(int i=1;i<=n;i++)
{
a[i].op=getchar();
switch(a[i].op)
{
case 'r':
getchar(),getchar();
case 'f':
getchar();
case 'a':
getchar(),getchar(),getchar();
}
scanf("%d%d",&a[i].a.first,&a[i].a.second),getchar();
a[i].f=EMPTY;
a[i].et=nt+1;
a[i].st=t;
if(a[i].op=='a')
m[zll(a[i].a)]=i;
else if(a[i].op=='r')
{
c1=zll(a[i].a);
a[m[c1]].et=t;
m.erase(m.find(c1));
a[i]={};
i--;
n--;
}
else
{
a[i].a.first++;
a[i].a.second++;
}
t++;
}
for(int i=1;i<=n;i++)
b[i]=a+i;
sort(b+1,b+n+1,cmpy);
fen(1,n);
for(int i=1;i<=n;++i)
{
if(a[i].op=='f')
{
if(a[i].f!=EMPTY)
printf("%d %d\n",a[i].f.F,a[i].f.S);
else
putchar('-'),putchar('1'),putchar('\n');
}
}
return 0;
}
稍微正常的程序tle22 快读快写试过,但是感觉没用所以删了