2012中南大学校赛F题 - 旋转卡壳的思维...

http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1165

       当时做计算机几何的时候也没练过旋转卡壳...对于一类求最小满足条件的区间问题..这种思维是很重要的...

       就如同本题...实际上就是要使得从a,b,c中取出的数尽量靠近.. 题目所给的a,b,c已经有序...用三个指针x,y,z来记录当前所在a,b,c的位置..每次在计算完a[x],b[y],c[z]后..将x,y,z都尝试性的往后移一位..找到min(a[x+1],b[y+1,c[z+1])...并真正移动那一位..直到x=an...b=bn....c=cn....这里有个比较好的预处理..就是将a[an+1]=oo  b[bn+1]=oo  c[cn+1]=oo 这样在做指针移动时..就可以不讨论越界问题了...


Program:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<queue>
#define oo 2000000000
#define ll long long
#define get(a,b,c) (a-b)*(a-b)+(a-c)*(a-c)+(b-c)*(b-c)
using namespace std;
int n[3],x,y,z;
ll s[3][1000005],t,ans,a,b,c;
int main()
{   
       freopen("input.txt","r",stdin);
       freopen("output.txt","w",stdout);
       while (~scanf("%d%d%d",&n[0],&n[1],&n[2]))
       {
              for (y=0;y<3;y++)
              {
                      for (x=1;x<=n[y];x++) scanf("%lld",&s[y][x]);  
                      s[y][x]=oo;
              }
              x=y=z=1;  
              ans=get(s[0][x],s[1][y],s[2][z]);
              while (x<=n[0] && y<=n[1] && z<=n[2])
              { 
                      t=get(s[0][x],s[1][y],s[2][z]);
                      a=s[0][x+1];  b=s[1][y+1];  c=s[2][z+1];
                      if (t<ans) ans=t;
                      if (a<=b && a<=c) x++; else
                      if (b<=a && b<=c) y++; else 
                      z++;
              }
              printf("%lld\n",ans);
       }
       return 0;
}



你可能感兴趣的:(c,OO)