hdu 4189 SWERC 2011 C - Cybercrime Donut Investigation

2023-12-27 22:10

本文主要是介绍hdu 4189 SWERC 2011 C - Cybercrime Donut Investigation,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://acm.hdu.edu.cn/showproblem.php?pid=4189

题意说是一个数据库,有n(n<=100, 000)个甜甜圈,每个甜甜圈有两个属性l,w.  (l,w<10^9)

后面有q个询问,会输入q(q<=50, 000)个罪犯的属性l,w。然后输出每个罪犯与数据库中的资料的最小相似度。相似度是  abs(l1-l2)+abs(w1,w2)。

其实如果把属性看做坐标值的话, 相似度就是两个点的绝对距离。

_____________________________________________________

下面分析,n和q都很大,证明这题不水。。。。 

把问题放到坐标图上,我们看着这些一个个的点来讨论。

首先,图上会出现n个坐标点,然后会出现q个询问,让你找出这n个点中,与他绝对距离最小的值。

这个问题也很难处理,还要讨论询问坐标(qx,qy) 与 那n个点的距离没有出现一个规则让你去排序或者贪心来找。

关键就是 abs里面 是会有正负,距离价值无法定位。

那我们再把问题简化,如果我们假设,出现的(qx,qy) 对于任意一个数据库中的 (xi,yi) 都满足 (qx>=xi,qy>=yi) 。

这样的话我们是不是 这个去找 xi+yi 值 尽可能大的值 来使得 dis=(qx-xi)+(qy-yi)  尽可能的小!

 

上面其实已经把 问题解决了,后面就是代码实现的问题了,我们只需要去 定义四种 规则 

1  (qx>=xi,qy>=yi) 

2  (qx>=xi,qy<=yi) 

3  (qx<=xi,qy>=yi) 

4  (qx<=xi,qy<=yi)

后面寻找使得dis 最小的 值

代码的实现我是把n+q个点放一起排序,

比如第一种情况 :在扫到询问点时,满足 qx>xi, 当qx==xi时 qy>=yi 

但是在之前的点必然会出现 qx>xi&&qx<yi  这些不满足  (qx>=xi,qy>=yi) 的点。

这个用线段树来规划一下范围,然后在规定的范围内进行查找就不会碰到(qx<yi)的点了。

而扫到数据库中的点,就放入线段树更新。

 

其实代码可以只扫两边,但是,为了思路明确(关键是懒得改了),我把四种情况都分别排序建树查询。

复杂度 (n+q)*log(n+q)

附上代码

View Code
  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <algorithm>
  6 using namespace std;
  7 #define N 100010
  8 #define M 260010
  9 typedef long long LL;
 10 struct node{
 11     LL x,y;
 12     int id;
 13 }w[150010];
 14 LL ty[150010],ans[100010];
 15 int ny;
 16 struct Tree{
 17     int l,r;
 18     LL val;
 19 }tree[1050010];
 20 bool cmp1(const node &a,const node &b){
 21     if(a.x!=b.x) return a.x<b.x;
 22     if(a.y!=b.y) return a.y<b.y;
 23     return a.id<b.id;
 24 }
 25 bool cmp2(const node &a,const node &b){
 26     if(a.x!=b.x) return a.x<b.x;
 27     if(a.y!=b.y) return a.y>b.y;
 28     return a.id<b.id;
 29 }
 30 bool cmp3(const node &a,const node &b){
 31     if(a.x!=b.x) return a.x>b.x;
 32     if(a.y!=b.y) return a.y<b.y;
 33     return a.id<b.id;
 34 }
 35 bool cmp4(const node &a,const node &b){
 36     if(a.x!=b.x) return a.x>b.x;
 37     if(a.y!=b.y) return a.y>b.y;
 38     return a.id<b.id;
 39 }
 40 int findy(LL y){
 41     int l=0,r=ny-1;
 42     while(l<=r){
 43         int mid=(l+r)>>1;
 44         if(ty[mid]<y) l=mid+1;
 45         else if(ty[mid]>y) r=mid-1;
 46         else return mid+1;
 47     }
 48 }
 49 void build(int L,int R,int x){
 50     tree[x].l=L;
 51     tree[x].r=R;
 52     tree[x].val=1000000000000;
 53     if(L==R) return ;
 54     int mid=(L+R)>>1;
 55     build(L,mid,x<<1);
 56     build(mid+1,R,x<<1|1);
 57 }
 58 LL find(int L,int R,int x){
 59     if(tree[x].l>=L&&tree[x].r<=R)
 60         return tree[x].val;
 61     
 62     int mid=(tree[x].l+tree[x].r)>>1;
 63     if(R<=mid) return find(L,R,x<<1);
 64     if(L>mid) return find(L,R,x<<1|1);
 65     return min(find(L,mid,x<<1),find(mid+1,R,x<<1|1));
 66 }
 67 void update(int id,int x,LL val){
 68     if(tree[x].l==tree[x].r){
 69         tree[x].val=min(tree[x].val,val);
 70         return ;
 71     }
 72     int mid=(tree[x].l+tree[x].r)>>1;
 73     if(id<=mid) update(id,x<<1,val);
 74     else update(id,x<<1|1,val);
 75     tree[x].val=min(tree[x<<1].val,tree[x<<1|1].val);
 76 }
 77 int main(){
 78     int n,q,cs=0;
 79     while(scanf("%d",&n)&&n!=-1){
 80         if(cs) printf("\n");
 81         else cs=1;
 82         for(int i=0;i<n;++i){
 83             scanf("%lld%lld",&w[i].x,&w[i].y);
 84             w[i].id=-1;
 85             ty[i]=w[i].y;
 86         }
 87         scanf("%d",&q);
 88         for(int i=0;i<q;++i){
 89             ans[i]=1000000000000;
 90             scanf("%lld%lld",&w[i+n].x,&w[i+n].y);
 91             w[i+n].id=i;
 92             ty[i+n]=w[i+n].y;
 93         }
 94         sort(ty,ty+n+q);
 95         ny=0;
 96         for(int i=1;i<n+q;++i)
 97             if(ty[i]!=ty[ny]) ty[++ny]=ty[i];
 98         ny++;
 99 
100 
101         
102         LL my=ty[ny-1],iy=ty[0];
103         //1
104         build(1,ny,1);
105         sort(w,w+n+q,cmp1);
106         LL mx=w[n+q-1].x,ix=w[0].x;
107         for(int i=0;i<n+q;++i){
108             if(w[i].id!=-1){
109                 int j=findy(w[i].y);
110                 ans[w[i].id]=min(ans[w[i].id],find(1,j,1)-(my-w[i].y)-(mx-w[i].x));
111             }
112             else update(findy(w[i].y),1,(my-w[i].y)+(mx-w[i].x));
113         }
114 
115         //2
116         build(1,ny,1);
117         sort(w,w+n+q,cmp2);
118         for(int i=0;i<n+q;++i){
119             if(w[i].id!=-1){
120                 int j=findy(w[i].y);
121                 ans[w[i].id]=min(ans[w[i].id],find(j,ny,1)-(w[i].y-iy)-(mx-w[i].x));
122             }
123             else update(findy(w[i].y),1,(w[i].y-iy)+(mx-w[i].x));
124         }
125 
126         //3
127         build(1,ny,1);
128         sort(w,w+n+q,cmp3);
129         for(int i=0;i<n+q;++i){
130             if(w[i].id!=-1){
131                 int j=findy(w[i].y);
132                 ans[w[i].id]=min(ans[w[i].id],find(1,j,1)-(my-w[i].y)-(w[i].x-ix));
133             }
134             else update(findy(w[i].y),1,(my-w[i].y)+(w[i].x-ix));
135         }
136 
137         //4
138         build(1,ny,1);
139         sort(w,w+n+q,cmp4);
140         for(int i=0;i<n+q;++i){
141             if(w[i].id!=-1){
142                 int j=findy(w[i].y);
143                 ans[w[i].id]=min(ans[w[i].id],find(j,ny,1)-(w[i].y-iy)-(w[i].x-ix));
144             }
145             else update(findy(w[i].y),1,(w[i].y-iy)+(w[i].x-ix));
146         }
147         for(int i=0;i<q;++i) printf("%lld\n",ans[i]);
148     }
149     return 0;
150 }

转载于:https://www.cnblogs.com/slon/archive/2012/03/30/2426104.html

这篇关于hdu 4189 SWERC 2011 C - Cybercrime Donut Investigation的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/544435

相关文章

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

hdu 3790 (单源最短路dijkstra)

题意: 每条边都有长度d 和花费p,给你起点s 终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。 解析: 考察对dijkstra的理解。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstrin

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

hdu 1102 uva 10397(最小生成树prim)

hdu 1102: 题意: 给一个邻接矩阵,给一些村庄间已经修的路,问最小生成树。 解析: 把已经修的路的权值改为0,套个prim()。 注意prim 最外层循坏为n-1。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstri

hdu 1285(拓扑排序)

题意: 给各个队间的胜负关系,让排名次,名词相同按从小到大排。 解析: 拓扑排序是应用于有向无回路图(Direct Acyclic Graph,简称DAG)上的一种排序方式,对一个有向无回路图进行拓扑排序后,所有的顶点形成一个序列,对所有边(u,v),满足u 在v 的前面。该序列说明了顶点表示的事件或状态发生的整体顺序。比较经典的是在工程活动上,某些工程完成后,另一些工程才能继续,此时