CF#509 Div2
A.Heist
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 const int N=1010; 6 int n; int a[N]; 7 int main() { 8 scanf("%d",&n); 9 for (int i=1;i<=n;i++) 10 scanf("%d",&a[i]); 11 sort(a+1,a+1+n); 12 printf("%d\n",a[n]-a[1]+1-n); 13 return 0; 14 }
B.Buying a TV Set
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 typedef long long ll; 5 ll gcd(ll x,ll y) { 6 if (!y) return x; 7 return gcd(y,x%y); 8 } 9 int main() { 10 ll a,b,x,y; 11 scanf("%I64d%I64d",&a,&b); 12 scanf("%I64d%I64d",&x,&y); 13 ll t=gcd(x,y); 14 x/=t,y/=t; 15 ll ans=min(a/x,b/y); 16 printf("%I64d\n",ans); 17 return 0; 18 }
C.Coffee Break
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <set> 5 using namespace std; 6 const int N=200010; 7 int n,m,d,ans,date[N]; 8 struct data { 9 int id,val; 10 data(){} 11 data(int I,int V):id(I),val(V){} 12 bool operator < (const data &A) const { 13 return val<A.val; 14 } 15 }; 16 set<data> S; 17 set<data>::iterator it; 18 int main() { 19 scanf("%d%d%d",&n,&m,&d); 20 for (int x,i=1;i<=n;i++) { 21 scanf("%d",&x); 22 S.insert(data(i,x)); 23 } 24 data now(0,m); 25 for (int i=1;i<=n;i++) { 26 it=S.upper_bound(now); 27 if (it==S.end()) 28 it=S.begin(),ans++; 29 now.val=it->val+d; 30 date[it->id]=ans; 31 S.erase(it); 32 } 33 printf("%d\n",ans); 34 for (int i=1;i<=n;i++) { 35 if (i==n) printf("%d\n",date[i]); 36 else printf("%d ",date[i]); 37 } 38 return 0; 39 }
D.Glider
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 const int N=200010; 6 int n,h,ans; 7 int a[N],c[N]; 8 struct data { 9 int l,r; 10 data(){} 11 data(int L,int R):l(L),r(R){} 12 bool operator < (const data &A) const { 13 return l<A.l; 14 } 15 }q[N]; 16 int main() { 17 scanf("%d%d",&n,&h); 18 for (int l,r,i=1;i<=n;i++) { 19 scanf("%d%d",&l,&r); 20 q[i]=data(l,r); 21 } 22 sort(q+1,q+1+n); 23 for (int i=1;i<=n;i++) { 24 a[i]=q[i].r-q[i].l; 25 c[i]=q[i].l-q[i-1].r; 26 } 27 int ed=0,cost=0,now; 28 for (int st=1;st<=n;st++) { 29 if (ed<st) 30 ed++,now=a[ed]; 31 while(ed<n&&cost+c[ed+1]<h) 32 ed++,cost+=c[ed],now+=a[ed]; 33 ans=max(ans,now); 34 now-=a[st]; 35 if (st<ed) cost-=c[st+1]; 36 } 37 printf("%d\n",ans+h); 38 return 0; 39 }
E.Tree Reconstruction
题目大意:有一棵$n$个点的树,给出$n-1$个数对,表示断了某条边之后剩余俩个连通块的最大节点编号,让你构造出一颗合法的树。
做法:观察发现一定有数对中一定有$n$,统计另外一个数的出现次数,我的构造方法构造若干条链,对于出现了$k$次的数可由$k-1$个比它小的数作为祖先节点,这样可以保证若不满足该条件,则一定不可能。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 const int N=1010; 6 int n,top; 7 int cnt[N],tmp[N],fa[N]; 8 int main() { 9 scanf("%d",&n); 10 for (int a,b,i=1;i<n;i++) { 11 scanf("%d%d",&a,&b); 12 if (a>b) swap(a,b); 13 if (b!=n) { 14 printf("NO\n"); 15 return 0; 16 } 17 cnt[a]++; 18 } 19 for (int i=1;i<n;i++) { 20 if (!cnt[i]) tmp[++top]=i; 21 else { 22 int x=cnt[i]-1; 23 if (top<x) { 24 printf("NO\n"); 25 return 0; 26 } 27 else { 28 int last=i; 29 for (int t,j=1;j<=x;j++) 30 t=tmp[top--],fa[last]=t,last=t; 31 fa[last]=n; 32 } 33 } 34 } 35 printf("YES\n"); 36 for (int i=1;i<n;i++) 37 printf("%d %d\n",i,fa[i]); 38 return 0; 39 }
F.Ray in the tube
题目大意:给俩面平行的镜子,镜子上有一些检测器,你可以任选入射光方向和起始位置,问最多能射到几个检测器。
做法:第一反应是想办法去找等差数列,然后就对着这道题看了50min,太沙茶了……
正解是你考虑如果最后答案的公差是3,那么选择公差是1的数列也是可行的,所以只需要考虑的是公差为2的若干次幂的情况,因为会涉及到光来回照射的问题。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <map> 5 using namespace std; 6 const int N=100010; 7 int n,m,y; 8 int a[N],b[N]; 9 map<int,int> M; 10 map<int,int>::iterator it; 11 int solve(int d) { 12 int dd=d*2,res=0; 13 M.clear(); 14 for (int i=1;i<=n;i++) 15 M[a[i]%dd]++; 16 for (int i=1;i<=m;i++) 17 M[(b[i]+d)%dd]++; 18 for (it=M.begin();it!=M.end();it++) 19 res=max(res,it->second); 20 return res; 21 } 22 int main() { 23 scanf("%d%d",&n,&y); 24 for (int i=1;i<=n;i++) 25 scanf("%d",&a[i]); 26 scanf("%d%d",&m,&y); 27 for (int i=1;i<=m;i++) 28 scanf("%d",&b[i]); 29 int d=1,ans=2; 30 for (int i=1;i<=30;i++) { 31 ans=max(ans,solve(d)); 32 d<<=1; 33 } 34 printf("%d\n",ans); 35 return 0; 36 }

浙公网安备 33010602011771号