[分治 杂题] Codeforces Gym 101173 CERC 16 G & BZOJ 4792 Geohash Grid

来源:互联网 发布:win10缺少—个网络协议 编辑:程序博客网 时间:2024/06/05 14:51

先转化问题

这里写图片描述
这里写图片描述
这里写图片描述

If we lay down numbers on a single line and mark numbers within the polyline, We obtain the optimal k-approximation by removing k1 largest gaps.

我们考虑怎么求gap 我们把网格切成两半的时候也就是把值域切成了两半 我们只要递归模拟返回区间内最大最小值就可以求出所有gap

这里写图片描述

这样的gap会有很多 肯定会炸 其实我们可以证明gap的大小不会很多 是O(nm)

这里写图片描述

我们用2i大小的矩形去切多边形时 每一个切对应一个gap
而因为本质不同的切是O(m)的 只有大概边和顶点这么多种
对于所有size 不同的gap就是O(nm)

算法就很明显了

Finally, we’ll revise our gap-finding algorithm, not to visit both children when the split would result in two tiles that look the same with respect to intersecting with the polygon. Instead we visit only one children, but create twice as many gaps in that branch.
It can be shown that this way we’ll only visit O(nm2) states. We have to look at the polygon through the viewport at every state to determine whether to split, so we have a total complexity of O(nm3) to find all gaps.

#include<cstdio>#include<cstdlib>#include<algorithm>#include<map>using namespace std;typedef long long ll;typedef pair<ll,ll> abcd;inline char nc(){  static char buf[100000],*p1=buf,*p2=buf;  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void read(int &x){  char c=nc(),b=1;  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}const int M=205;int n,m;int x[M],y[M];map<ll,ll> Map;typedef map<ll,ll>::reverse_iterator ITER;#define _y1 min(y[i],y[j])#define _y2 max(y[i],y[j])#define _x1 min(x[i],x[j])#define _x2 max(x[i],x[j])inline abcd Solve(int x1,int y1,int x2,int y2,ll v0,ll t){  ll dx=x2-x1,dy=y2-y1,dv=(x2-x1)*(y2-y1)/2;  int ins=0,p=0,h=0,v=0;  for (int i=0,j=1;i<m;i++,j=(++j)%m){    p|=x[i]>x1 && x[i]<x2 && y[i]>y1 && y[i]<y2;    ins^=x[i]==x[j] && x[i]<=x1 && _y1<=y1 && y1<_y2;    h|=x[i]!=x[j] && y[i]>y1 && y[i]<y2 && max(_x1,x1)<min(_x2,x2);    v|=x[i]==x[j] && x[i]>x1 && x[i]<x2 && max(_y1,y1)<min(_y2,y2);  }  if (!p && !v && !h)     return ins?abcd(v0,v0+dx*dy-1):abcd(1LL<<40,-1LL<<40);  abcd a,b;  if (dx==dy){    if (!p && h)      a=Solve(x1,y1,(x1+x2)/2,y2,v0,t<<1),b=abcd(a.first+dv,a.second+dv);    else      a=Solve(x1,y1,(x1+x2)/2,y2,v0,t),b=Solve((x1+x2)/2,y1,x2,y2,v0+dv,t);  }else{    if (!p && v)      a=Solve(x1,y1,x2,(y1+y2)/2,v0,t<<1),b=abcd(a.first+dv,a.second+dv);    else      a=Solve(x1,y1,x2,(y1+y2)/2,v0,t),b=Solve(x1,(y1+y2)/2,x2,y2,v0+dv,t);  }  if (a.second!=-1LL<<40 && b.first!=1LL<<40 && a.second+1<b.first)    Map[b.first-a.second-1]+=t;  return abcd(min(a.first,b.first),max(a.second,b.second));}int p;ll val[1000005],cnt[1000005],sum[1000005];int main(){  freopen("t.in","r",stdin);  freopen("t.out","w",stdout);  read(n); read(m); for (int i=0;i<m;i++) read(x[i]),read(y[i]);  abcd t=Solve(0,0,1<<n,1<<n,0,1);  ll ans=t.second-t.first+1;  for (ITER it=Map.rbegin();it!=Map.rend();it++){    val[++p]=it->first;    cnt[p]=cnt[p-1]+it->second;    sum[p]=sum[p-1]+it->first*it->second;  }  int Q,K;  read(Q);  while (Q--){    read(K); K--; int it=lower_bound(cnt+1,cnt+p+1,K)-cnt;    printf("%lld\n",ans-(sum[it-1]+(K-cnt[it-1])*val[it]));  }  return 0;}
0 0
原创粉丝点击