您的位置:首页 > 编程语言 > Go语言

Problem B. gFiles Google APAC 2016 University Test Round C

2017-02-16 19:35 423 查看
由于记录的百分比误差在1%范围内,因此给定Pi,Ki, 对应的文件总数在范围(100*Ki/(Pi+1),100*Ki/Pi]。两个端点都是下取整,因为文件数是整数,e.g., (4.71,5.3] is equal to (4,5]。

对于每一组Ki,Pi,对应的区间(li,ri]。只需要保证这些区间的交集只有一个点就OK了。将这些区间的端点存在Point中,按照val (=li or ri) 从小大大排序。遍历一遍就可以得知每个端点被多少个区间覆盖。因为区间是左开右闭,应该从右往左遍历。

然后从右往左遍历,判断有木有端点的覆盖次数是N。如果第i个端点被N个区间覆盖,那么i到i-1的差值(val_i - val_{i-1})对应的整数点的覆盖次数都是N。最后只要判断这些点是否只有一个即可。

Some Remarks, 从problem statement看来,测试数据只有仅有一个解和有多个解两个case。我开始一直在纠结Ki,Pi有contradiction如何处理,i.e., P1,K1 and P2,K2对应的区间没有交集。

如果Pi=0, then 100*Ki/Pi=100*Ki/epa=inf。 那么对应的区间就是(0,inf],可以将inf设成answer的上界。即使此时Ki=0也木有影响,因为Pi=0,Ki=0对应为文件总数本身就是整个solution
space。

对于Pi=100要单独判断。因为对应的区间只有一个点,无法通过val_i - val_{i-1}找出中间整数点的覆盖次数。e.g.,N=3,对于区间(3,6],[5],(2,5]本身ans=5是合法的,但是按照上述方法就会得出覆盖次数=3的点是4,5两个。

#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<set>

using namespace std;

//2016 Round C Problem B. gFiles
int T;
const int maxn=110;
int N;
long long K[maxn];
int P[maxn];
long long ans;
const long long upper=1e15;//use int initially, then it causes WA in large data
class node
{
public:
long long val;
int pointidx;
bool start;
int cover;
public:
node()
{
val=0;
pointidx=0;
start=false;
cover=0;
}
node(long long v,int p,bool s)
{
val=v;
pointidx=p;
start=s;
cover=0;
}
};
bool cmp(node a,node b)
{
if(a.val==b.val)
{
return a.start>b.start;
}
return a.val<b.val;
}
node Point[maxn*2];
int totN;
int main()
{
freopen("B-small-practice.in","r",stdin);
// freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d",&T);
for(int ca=1;ca<=T;ca++)
{
memset(K,0,sizeof(K));
memset(P,0,sizeof(P));
ans=0;
scanf("%d",&N);
bool flg=false;
for(int i=0;i<N;i++)
{
scanf("%d %lld",&P[i],&K[i]);
if(P[i]==100&&flg==false)
{
printf("Case #%d: %lld\n",ca,K[i]);
flg=true;
}
}
if(flg==true)
{
continue;
}
// if(P[0]==100)
// {
// printf("Case #%d: %lld\n",ca,K[0]);
// continue;
// }
int cnt=0;
totN=N;
for(int i=0;i<N;i++)
{
if(P[i]==100)
{
Point[cnt++]=node(K[i],i,false);
}
// else if(K[i]==0)
// {
//// cout<<"i "<<i<<endl;
// totN--;
// //continue;
// }
else
{
long long left=100*K[i]/(P[i]+1);
long long right=0;
if(P[i]>0)
{
right=100*K[i]/P[i];
right=min(upper,right);
}
else
{
right=upper;
// if(K[i]>0)
// {
// right=2000;//for small input
// }
// else
// {
// right=0;
// }
}
Point[cnt++]=node(left,i,true);
//cout<<i<<" "<<cnt<<endl;
Point[cnt++]=node(right,i,false);
//cout<<i<<" "<<cnt<<endl;
}
}

sort(Point,Point+cnt,cmp);
Point[cnt-1].cover=1;
for(int i=cnt-2;i>=0;i--)
{
if(Point[i].start==false)
{
Point[i].cover=Point[i+1].cover+1;
}
else
{
Point[i].cover=Point[i+1].cover-1;
}
}
// cout<<cnt<<endl;
// for(int i=0;i<cnt;i++)
// {
// cout<<Point[i].pointidx<<" "<<Point[i].val<<" "<<Point[i].start<<" "<<Point[i].cover<<endl;
// }
// set<long>mark=set<long>();
long long len=0;
for(int i=cnt-1;i>=0;i--)
{
if(Point[i].cover==totN)
{
if(i==0)
{
len+=1;
ans=Point[i].val;
}
else
{
if(Point[i].val-Point[i-1].val>1)
{
len=0;
break;
}
len+=Point[i].val-Point[i-1].val;//i must be >0
ans=Point[i].val;
}
// if(i==0)
// {
//
// }
// else
// {
// ans+=Point[i].val-Point[i-1].val;
// }
// ans=Point[i].val;
// mark.insert(Point[i].val);//repeated elements will be count as 1?
}
}
// if(mark.size()!=1)
// cout<<totN<<" "<<len<<endl;
if(len!=1)
{
ans=-1;
}
printf("Case #%d: %lld\n",ca,ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: