http://acm.hdu.edu.cn/showproblem.php?pid=4631
題意: 在平面內依次加點,求每次加點后最近點對距離平方的和
因為是找平面最近點對...所以加點以后這個最短距離一定是遞減的...所以最后會形成這樣一個函數圖像
所以我們只要從后往前依次刪點即可...
15秒驚險水過...不過我最小點對的木板肯定寫掛了,卡時限的話估計過不了...
請用G++交...C++會TLE...當然我也無法解釋這個問題...估計是我傻逼
?
/********************* Template ************************/ #include <set> #include <map> #include <list> #include <cmath> #include <ctime> #include <deque> #include <queue> #include <stack> #include <bitset> #include <cstdio> #include <string> #include <vector> #include <cassert> #include <cstdlib> #include <cstring> #include <sstream> #include <fstream> #include <numeric> #include <iomanip> #include <iostream> #include <algorithm> #include <functional> using namespace std;#define EPS 1e-8 #define MAXN (int)5e5+5 #define MOD (int)1e9+7 #define PI acos(-1.0) #define INF ((1LL)<<50) #define max(a,b) ((a) > (b) ? (a) : (b)) #define min(a,b) ((a) < (b) ? (a) : (b)) #define max3(a,b,c) (max(max(a,b),c)) #define min3(a,b,c) (min(min(a,b),c)) #define BUG cout<<"BUG! "<<endl #define LINE cout<<"------------------"<<endl #define L(t) (t << 1) #define R(t) (t << 1 | 1) #define Mid(a,b) ((a + b) >> 1) #define lowbit(a) (a & -a) #define FIN freopen("out.txt","w",stdout) #pragma comment (linker,"/STACK:102400000,102400000")// typedef long long LL; // typedef unsigned long long ULL; typedef __int64 LL; // typedef unisigned __int64 ULL; // int gcd(int a,int b){ return b?gcd(b,a%b):a; } // int lcm(int a,int b){ return a*b/gcd(a,b); }/********************* F ************************/ struct point {LL x,y;int pos;int id;point(double a = 0,double b = 0,int c = 0){x = a ; y = b ; pos = c;} }p[MAXN],t[MAXN],tmp[MAXN];LL n,ax,bx,cx,ay,by,cy;bool cmp(point a,point b){if(a.x == b.x) return a.y < b.y;return a.x < b.x; }bool cmp1(point a,point b){return a.y < b.y; }LL dist(point a ,point b){return (a.x-b.x) * (a.x-b.x) + (a.y-b.y) * (a.y-b.y); }/** 二維空間找最近點對* 返回排序后點位置的pair<int,int>*/ pair<int,int> Closest_Pair(int l ,int r){if(l == r || l+1 == r) return make_pair(l,r); //1個點,2個點 直接return;int m = Mid(l,r); // (l+r)/2pair<int,int> dl = Closest_Pair(l,m);pair<int,int> dr = Closest_Pair(m+1,r);LL ldis,rdis; //左部分的最值 右部分的最值LL ans_dis; //左中右三部分最值if(dl.first == dl.second) ldis = INF; //判重else ldis = dist(p[dl.first],p[dl.second]);if(dr.first == dr.second) rdis = INF;else rdis = dist(p[dr.first],p[dr.second]);pair<int,int> ans = ldis < rdis ? dl : dr ; //左右兩部分的最值點對ans_dis = min(ldis,rdis); //左右兩部分的最值// 從中向左右兩邊找在[p[m].x-d,p[m].x+d]的平面內所有點// 這以后的復雜度就不太好估計了...// 這段模板是用暴力找的...我只做了一點點優化...但為什么加剪枝時間還多了這我不太理解囧int cnt = 0; // for(int i = l; i <= r; i++) // { // if((long long)(p[m].x - p[i].x)*(p[m].x - p[i].x) <= ans_dis) // tmp[cnt++] = p[i]; // }for(int i = m ; i >= l ; i--){LL q = (p[m].x - p[i].x) * (p[m].x - p[i].x);if(p[i].x < p[m].x - q) break;if(q <= ans_dis){tmp[cnt++] = p[i];}}for(int i = m+1 ; i <= r ; i++){LL q = (p[m].x - p[i].x) * (p[m].x - p[i].x);if(p[i].x > p[m].x + q) break;if(q <= ans_dis){tmp[cnt++] = p[i];}}//按y方向進行篩選 ,相隔大于d的點可以直接跳過sort(tmp,tmp+cnt,cmp1);for(int i = 0 ; i < cnt ; i++){for(int j = i+1 ; j < cnt ; j++){if((tmp[i].y - tmp[j].y) * (tmp[i].y - tmp[j].y) >= ans_dis)break;if(dist(tmp[i],tmp[j]) < ans_dis){ans_dis = dist(tmp[i],tmp[j]);ans = make_pair(tmp[i].id,tmp[j].id);}}}return ans; }void pre(){t[0].x = bx % cx;t[0].y = by % cy;t[0].pos = 0;for(int i = 1 ; i <= n ; i++) {t[i].x = (t[i-1].x * ax + bx) % cx;t[i].y = (t[i-1].y * ay + by) % cy;t[i].pos = i;} } int main() {//FIN;int T;scanf("%d",&T);while(T--){scanf("%d%I64d%I64d%I64d%I64d%I64d%I64d",&n,&ax,&bx,&cx,&ay,&by,&cy);pre();LL res = 0 ;while(n){for(int i = 0 ; i < n ; i++)p[i] = t[i];sort(p,p+n,cmp);for(int i = 0 ; i < n ; i++)p[i].id = i;pair<int,int> ans = Closest_Pair(0,n-1);int last = max(p[ans.first].pos,p[ans.second].pos);res += (dist(p[ans.first],p[ans.second]) * (n - last));n = last ;}printf("%I64d\n",res);}return 0; }
?