hdu4311
来源:互联网 发布:知其不可奈何安之若命 编辑:程序博客网 时间:2024/06/06 13:04
/*
分析:
树状数组+二分(可以不用二分)。
果真是流年不利么。。。一开始就考虑会爆int的,就想到用64位了,
结果代码敲着敲着、一部分还是用了int,敲傻了么,1wa,囧~。。。
简单说下思路吧:
假设现在有n个点,把这些点都画到坐标纸上后第i个点在最左边、
同时也是最下面,
那么,假设大家都到i这里来:
第一个人到i这里,要走x1-xi+y1-yi;
第二个人到i这里,要走x2-xi+y2-yi;
。。。。。。
第n个人道i这里,要走 xn-xi+yn-yi;
(看出来思路没?)简单整合一下,不就是:
ans=(x1+x2+x3+...+xn)-n*xi+(y1+y2+...+yn)-n*yi;
(括号里面的sum部分可以用树状数组、线段树呀来维护)
但是,有些x<xi、有些x>xi,怎么办呢?那就将所有的x都排个序,
再将所有的y排个序,同时让每个x记住自己对应的y值在排序后到了哪儿,
在排序之后,再列出这个树状数组(线段树)。
然后对x从小到大遍历,遍历的当前的点就作为当前的中心,让大
家都来这个点,这个时候,刚刚的“(x1+x2+...+xn)”就可以分为两个部
分了,一部分在当前点左边,一部分在当前点右边,这个借助树状数组
在log(n)的时间内求出x方向上的ans_x;再找到当前点对应的y值,用同
样的方法求出y方向上的ans_y,然后就可以得到ans=ans_x+ans_y了。
PS:
打字打上瘾了。。。
头有点儿晕,就懒一下,没有维护排序后x对应的y在哪里,用的方法是
每次都二分查找一下-、-I,不过只是大概让时间*2了而已,仍在可以接受范
围以内。。。
2012-12-12
*/
分析:
树状数组+二分(可以不用二分)。
果真是流年不利么。。。一开始就考虑会爆int的,就想到用64位了,
结果代码敲着敲着、一部分还是用了int,敲傻了么,1wa,囧~。。。
简单说下思路吧:
假设现在有n个点,把这些点都画到坐标纸上后第i个点在最左边、
同时也是最下面,
那么,假设大家都到i这里来:
第一个人到i这里,要走x1-xi+y1-yi;
第二个人到i这里,要走x2-xi+y2-yi;
。。。。。。
第n个人道i这里,要走 xn-xi+yn-yi;
(看出来思路没?)简单整合一下,不就是:
ans=(x1+x2+x3+...+xn)-n*xi+(y1+y2+...+yn)-n*yi;
(括号里面的sum部分可以用树状数组、线段树呀来维护)
但是,有些x<xi、有些x>xi,怎么办呢?那就将所有的x都排个序,
再将所有的y排个序,同时让每个x记住自己对应的y值在排序后到了哪儿,
在排序之后,再列出这个树状数组(线段树)。
然后对x从小到大遍历,遍历的当前的点就作为当前的中心,让大
家都来这个点,这个时候,刚刚的“(x1+x2+...+xn)”就可以分为两个部
分了,一部分在当前点左边,一部分在当前点右边,这个借助树状数组
在log(n)的时间内求出x方向上的ans_x;再找到当前点对应的y值,用同
样的方法求出y方向上的ans_y,然后就可以得到ans=ans_x+ans_y了。
PS:
打字打上瘾了。。。
头有点儿晕,就懒一下,没有维护排序后x对应的y在哪里,用的方法是
每次都二分查找一下-、-I,不过只是大概让时间*2了而已,仍在可以接受范
围以内。。。
2012-12-12
*/
#include"stdio.h"#include"string.h"#include"stdlib.h"#define N 100011int n;struct A{ int x,y;}E[N];int x[N],y[N];int lowbit[N];__int64 C[2][N];//0x、1yint cmp(const void *a,const void *b){ return *(int *)a-*(int *)b;}void get_lowbit(){ int i; for(i=1;i<=100000;i++) lowbit[i]=i&(-i);}__int64 sum(int K,int k){ __int64 p=0; while(k>0 && k<=n) { p+=C[K][k]; k-=lowbit[k]; } return p;}void update(int K,int k,int dir){ while(k>0 && k<=n) { C[K][k]+=dir; k+=lowbit[k]; }}void init(){ int i; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d%d",&E[i].x,&E[i].y); x[i]=E[i].x; y[i]=E[i].y; } x[0]=y[0]=-1111111111; qsort(x,n+1,sizeof(int),cmp); qsort(y,n+1,sizeof(int),cmp); memset(C,0,sizeof(C)); for(i=1;i<=n;i++) { update(0,i,x[i]); update(1,i,y[i]); }}__int64 solve(){ int i; int low,mid,up; __int64 a,b; __int64 sum_x,sum_y; __int64 temp,ans; ans=100011; ans*=1000000000; sum_x=sum(0,n); sum_y=sum(1,n); for(i=1;i<=n;i++) { low=1;up=n;mid=(low+up)>>1; while(low<=up) { if(x[mid]<E[i].x) low=mid+1; else up=mid-1; mid=(low+up)>>1; } a=sum(0,low); temp=(__int64)low*E[i].x-a+sum_x-a-(n-(__int64)low)*E[i].x; low=1;up=n;mid=(low+up)>>1; while(low<=up) { if(y[mid]<E[i].y) low=mid+1; else up=mid-1; mid=(low+up)>>1; } b=sum(1,low); temp+=(__int64)low*E[i].y-b+sum_y-b-(n-(__int64)low)*E[i].y; if(temp<ans) ans=temp; } return ans;}int main(){ int T; get_lowbit(); scanf("%d",&T); while(T--) { init(); printf("%I64d\n",solve()); } return 0;}
- hdu4311
- hdu4311
- HDU4311(排序+二分)
- hdu4311 曼哈顿距离
- hdu4311(排序)
- hdu4311 Meeting point-1 观察题
- HDU4311 Meeting point-1(曼哈顿距离)
- 某个点到其他点的曼哈顿距离之和最小(HDU4311)
- build.xml类 参考 (生成war)
- 程序员如何做出“不难看”的设计
- linux下dlopen的使用
- 玩转字符数组1
- Windows驱动开发WDM (10)- StartIo取消例程
- hdu4311
- ubuntu基本操作 - ssh的使用
- UVa 10003
- usaco-dith
- LINUX下动态链接库的使用
- Android中JSON详细总结
- ftp 用法:
- SQL SERVER 链接服务器设置 (Oracle to Sqlserver)
- usaco--stall4