BZOJ2716: [Violet 3]天使玩偶
题解:
kdtree裸题?
感觉判断是否进入左右子树真的是个估价函数。。。
inline int get(int k) { if(!k)return inf; int ret=0; for0(i,1)ret+=max(0,t[k].mi[i]-now[i]); for0(i,1)ret+=max(0,now[i]-t[k].mx[i]); return ret; }
我们来看这个函数
按我的理解,这就是在估计以k为根的子树中与now的距离最小是多少
然后就根据这个看看需不需要进入左右子树。。。
好没理由啊。。。怎么保证复杂度的。。。
代码:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #include<vector> 8 #include<map> 9 #include<set> 10 #include<queue> 11 #include<string> 12 #define inf 1000000000 13 #define maxn 500000+5 14 #define maxm 500+100 15 #define eps 1e-10 16 #define ll long long 17 #define pa pair<int,int> 18 #define for0(i,n) for(int i=0;i<=(n);i++) 19 #define for1(i,n) for(int i=1;i<=(n);i++) 20 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 21 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 22 #define for4(i,x) for(int i=head[x],y;i;i=e[i].next) 23 #define mod 1000000007 24 using namespace std; 25 inline int read() 26 { 27 int x=0,f=1;char ch=getchar(); 28 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 29 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 30 return x*f; 31 } 32 int n,m,cur,tot,rt,ans; 33 struct rec 34 { 35 int d[2],mi[2],mx[2],l,r; 36 int& operator[](int i){return d[i];} 37 }p[maxn],now,t[maxn<<1]; 38 bool operator<(rec a,rec b){return a[cur]<b[cur];} 39 inline int dis(rec a,rec b){return abs(a[0]-b[0])+abs(a[1]-b[1]);} 40 inline void pushup(int k) 41 { 42 int l=t[k].l,r=t[k].r; 43 for0(i,1) 44 { 45 t[k].mi[i]=min(t[k].mi[i],min(t[l].mi[i],t[r].mi[i])); 46 t[k].mx[i]=max(t[k].mx[i],max(t[l].mx[i],t[r].mx[i])); 47 } 48 } 49 int build(int l,int r,int dir) 50 { 51 cur=dir;int mid=(l+r)>>1; 52 nth_element(p+l,p+mid,p+r+1); 53 t[mid]=p[mid]; 54 for0(i,1)t[mid].mi[i]=t[mid].mx[i]=t[mid][i]; 55 if(l<mid)t[mid].l=build(l,mid-1,dir^1); 56 if(mid<r)t[mid].r=build(mid+1,r,dir^1); 57 pushup(mid); 58 return mid; 59 } 60 void insert(int &k,int dir) 61 { 62 if(!k) 63 { 64 k=++tot;t[tot]=now; 65 for0(i,1)t[tot].mi[i]=t[tot].mx[i]=t[tot][i]; 66 return; 67 } 68 if(now[dir]<t[k][dir])insert(t[k].l,dir^1); 69 else insert(t[k].r,dir^1); 70 pushup(k); 71 } 72 inline int get(int k) 73 { 74 if(!k)return inf; 75 int ret=0; 76 for0(i,1)ret+=max(0,t[k].mi[i]-now[i]); 77 for0(i,1)ret+=max(0,now[i]-t[k].mx[i]); 78 return ret; 79 } 80 void query(int k,int dir) 81 { 82 int dl=get(t[k].l),dr=get(t[k].r),d0=dis(t[k],now); 83 if(d0<ans)ans=d0; 84 if(dl<dr) 85 { 86 if(dl<ans)query(t[k].l,dir^1); 87 if(dr<ans)query(t[k].r,dir^1); 88 }else 89 { 90 if(dr<ans)query(t[k].r,dir^1); 91 if(dl<ans)query(t[k].l,dir^1); 92 } 93 } 94 int a[20]; 95 inline void print(int x) 96 { 97 if(!x)putchar('0'); 98 for(a[0]=0;x;x/=10)a[++a[0]]=x%10; 99 for3(i,a[0],1)putchar('0'+a[i]); 100 putchar('\n'); 101 } 102 int main() 103 { 104 freopen("input.txt","r",stdin); 105 freopen("output.txt","w",stdout); 106 n=read();m=read();tot=n; 107 for0(i,1)t[0].mi[i]=inf,t[0].mx[i]=-inf; 108 for1(i,n)p[i][0]=read(),p[i][1]=read(); 109 rt=build(1,n,0); 110 while(m--) 111 { 112 int op=read();now[0]=read();now[1]=read();ans=inf; 113 if(op==1)insert(rt,0);else query(rt,0),print(ans); 114 } 115 return 0; 116 }
加了输出优化还是没进第一版,好桑心QAQ
2716: [Violet 3]天使玩偶
Time Limit: 80 Sec Memory Limit: 128 MBSubmit: 569 Solved: 242
[Submit][Status]
Description
Input
Output