NC54379. Archery Tournament
描述
输入描述
The first line of the input contains integer n (1 ≤ n ≤ 2·105). Next n lines describe the events happening at the tournament. The i-th line contains three integers ti, xi, and yi (ti = 1, 2; −109 ≤ xi, yi ≤ 109; yi > 0).
• If ti = 1, then a new target with center (xi, yi) and radius yi appears at the range.
• If ti = 2, then you perform a shot, which hits the range at (xi, yi).
输出描述
For each of your shots, output a separate line with the single integer. If the shot did not hit any target, print “-1”. If the shot hit a target, print the number of event when that target was added to the range. Events are numbered starting from 1.
示例1
输入:
8 1 0 12 2 -11 22 1 24 10 1 12 3 2 12 12 2 16 14 1 28 15 2 3 6
输出:
-1 -1 3 1
说明:
C++14(g++5.4) 解法, 执行用时: 499ms, 内存消耗: 158456K, 提交时间: 2020-10-06 16:59:55
#include <bits/stdc++.h> using namespace std; int tot; vector<int> v[200005*20]; int ls[200005*20],rs[200005*20]; int x[200005],y[200005]; int ans; int check(int x1,int y1,int x2,int y2) { if(1ll*(x1-x2)*(x1-x2)+1ll*(y1-y2)*(y1-y2)<1ll*y1*y1) return 1; return 0; } void insert(int &now,int l,int r,int L,int R,int id) { if(!now) now=++tot; if(L<=l&&R>=r) { v[now].push_back(id); return ; } int mid=(l+r)>>1; if(L<=mid) insert(ls[now],l,mid,L,R,id); if(R>mid) insert(rs[now],mid+1,r,L,R,id); } void ask(int now,int l,int r,int xx,int yy) { if(!now) return ; for(int i=0;i<v[now].size();i++) if(check(x[v[now][i]],y[v[now][i]],xx,yy)) { ans=v[now][i]; return ; } if(l==r) return ; int mid=(l+r)>>1; if(xx<=mid) ask(ls[now],l,mid,xx,yy); else ask(rs[now],mid+1,r,xx,yy); } void del(int now,int l,int r,int L,int R) { if(L<=l&&R>=r) { vector<int> y; for(int i=0;i<v[now].size();i++) if(v[now][i]!=ans) y.push_back(v[now][i]); v[now]=y; return ; } int mid=(l+r)>>1; if(L<=mid) del(ls[now],l,mid,L,R); if(R>mid) del(rs[now],mid+1,r,L,R); } int main() { int n; scanf("%d",&n); int rt=0; tot=0; for(int i=1;i<=n;i++){ int t,xx,yy; scanf("%d%d%d",&t,&xx,&yy); if(t==1) x[i]=xx,y[i]=yy,insert(rt,-1e9,1e9,xx-yy,xx+yy,i); else { ans=-1; ask(rt,-1e9,1e9,xx,yy); printf("%d\n",ans ); if(ans!=-1) del(rt,-1e9,1e9,x[ans]-y[ans],x[ans]+y[ans]); } } }
C++(clang++11) 解法, 执行用时: 552ms, 内存消耗: 210000K, 提交时间: 2020-10-27 20:29:51
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=2e5+10; const int inf=1e9; int n,cnt,rt,ans; ll lx[N],ly[N]; int lc[N*30],rc[N*30]; vector<int>s[N*30]; inline void add(int &rt,int l,int r,int id,int x,int y) { if(!rt) rt=++cnt; if(l>=x&&r<=y) { s[rt].push_back(id); return ; } int mid=(l+r)>>1; if(x<=mid) add(lc[rt],l,mid,id,x,y); if(mid<y) add(rc[rt],mid+1,r,id,x,y); } inline void upd(int rt,int l,int r,ll x,ll y) { if(l>=x&&r<=y) { vector<int>tmp;int len=s[rt].size(); for (int i=0;i<len;i++) if(s[rt][i]!=ans) tmp.push_back(s[rt][i]); s[rt]=tmp; return ; } int mid=(l+r)>>1; if(x<=mid) upd(lc[rt],l,mid,x,y); if(mid<y) upd(rc[rt],mid+1,r,x,y); } inline bool check(ll u,ll v,ll x,ll y) { if((x-u)*(x-u)+(y-v)*(y-v)<v*v) return 1; return 0; } inline void find(int rt,int l,int r,ll x,ll y) { if(!rt) return ; int len=s[rt].size(); for (int i=0;i<len;i++) if(check(lx[s[rt][i]],ly[s[rt][i]],x,y)) {ans=s[rt][i];break;} int mid=(l+r)>>1; if(x<=mid) find(lc[rt],l,mid,x,y); else find(rc[rt],mid+1,r,x,y); } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) { int id;ll x,y; scanf("%d%lld%lld",&id,&x,&y); if(id==1) { lx[i]=x;ly[i]=y; add(rt,-inf,inf,i,x-y,x+y); } else { ans=-1; find(rt,-inf,inf,x,y); //抽象为单点查询 printf("%d\n",ans); if(ans!=-1) upd(rt,-inf,inf,lx[ans]-ly[ans],lx[ans]+ly[ans]); } } return 0; }