2016_1_13
小兵的故事
(bin.cpp/c/pas)
Time limited = 1500ms
小兵休息时喜欢打打炉石和刀塔,然而这在伟大的计算机房是不怎么允许的。
已知伟大的计算机房有两个房门:前门和后门。
这两个门都有着高超的科技,可以设定一个参数t。z
如果一个人会在T1时刻进来,那么就会在T1-t时刻把门打开,
但是如果下一个人在T2时刻进来:
(1)如果该T2-T1<=2t,那么门会在T2+t时刻关上
(2)否则,会先在T1+t时刻关上,T2-t时刻打开,T2+t时刻再关上。
如果两个门同时打开的时间超过d(一旦有任意一个门关上则重新计算),那么就会形成冷空气对流,小兵就会感觉到寒冷,高超的操作就会受到影响。
如果两个门开关的次数太多,就增加了被查房的风险。
小兵现在已经预测出午休时间两个门分别会在哪些时刻进来人,现在问题是如何设定前门和后门的两个参数:t1、t2(必须是>=1的整数)使得:
1、两个门同时打开的时间不超过d(一旦有任意一个门关上则重新计算)
2、两个门的打开的次数之和尽可能的小
输入描述:
第一行三个整数N,M,d
第二行N个整数,p1<p2<…<pN,表示前门会在哪些时刻进来人
第三行M个整数,q1<q2<…<qM,表示后门会在哪些时刻进来人
d,p,q<=10^9
10% N,M<=50
30% N,M<=500
100% N,M<=5000
输出描述:
一个整数Ans,表示两个门打开的次数之和。如果无解输出”No solution”(不包括引号。
输入样例:
3 2 4
1 6 13
7 11
输出样例:
3
好久没写随笔了今天写一发。。这道题其实蛮水的但是我码第二题去了我真是蠢。
首先发现了ta,tb对应的单调性的关系,ta增加,tb只可能不变或者减少。考虑到ta,tb各最多有5000个,直接暴力就好了。
交的时候我T了一次是因为check的时候用的n^2,蠢哭了。稍微改一下扫一遍就好。
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstdlib> 5 using namespace std; 6 const int N = 5003; 7 int ta[N],tb[N],lena,lenb; 8 int a[N],b[N],m,n,d; 9 int ans = 2000000000; 10 struct quiian { 11 int x,y; 12 }A[N],B[N]; 13 inline int Calc(int x,int y,int c,int d) { 14 int S = min(x,c); 15 int T = max(y,d); 16 return y-x + d-c -(T-S); 17 } 18 int main() { 19 freopen("bin.in","r",stdin); 20 freopen("bin.out","w",stdout); 21 scanf("%d%d%d",&n,&m,&d); 22 for(int i = 1 ; i <= n ; ++i) { 23 scanf("%d",&a[i]); 24 if(i>=2) ta[++lena] = (a[i] - a[i-1] + 1)/2; 25 } 26 ta[++lena] = 1; 27 sort(ta+1,ta+1+lena); 28 for(int i = 1 ; i <= m ; ++i) { 29 scanf("%d",&b[i]); 30 if(i>=2) tb[++lenb] = (b[i] - b[i-1] + 1)/2; 31 } 32 tb[++lenb] = 1; 33 sort(tb+1,tb+1+lenb); 34 int last = lenb; 35 for(int i = 1 ; i <= lena ; ++i) { 36 int cnt = 0,t1 = 0; 37 cnt++; 38 A[++t1].x = a[1] - ta[i]; 39 for(int j = 1 ; j < n ; ++j) { 40 if(a[j+1] - a[j] <= 2*ta[i]) continue; 41 A[t1].y = a[j] + ta[i]; 42 A[++t1].x = a[j+1] - ta[i]; 43 cnt++; 44 } 45 A[t1].y = a[n] + ta[i]; 46 bool flag = true; 47 do { 48 int cnt2 = 0,t2 = 0; 49 flag = true; 50 cnt2++; 51 B[++t2].x = b[1] - tb[last]; 52 for(int j = 1 ; j < m ; ++j) { 53 if(b[j+1] - b[j] <= 2* tb[last]) continue; 54 B[t2].y = b[j] + tb[last]; 55 B[++t2].x = b[j+1] - tb[last]; 56 cnt2++; 57 } 58 B[t2].y = b[m] + tb[last]; 59 int stt = 1; 60 for(int i = 1 ; i <= t1 ; ++i) { 61 if(A[i].y < B[stt].x) continue; 62 while(B[stt].y < A[i].x && stt<=t2) stt++; 63 if(stt>t2) break; 64 for(int j = stt ; j <= t2 ; ++j) { 65 if(B[j].x > A[i].y) break; 66 int linshi = Calc(A[i].x,A[i].y,B[j].x,B[j].y); 67 if(linshi > d) { 68 flag = false; break; 69 } 70 } 71 if(!flag) break; 72 } 73 if(!flag) last--; 74 else ans = min(ans,cnt + cnt2); 75 if(last==0) break; 76 }while(!flag); 77 if(last==0) break; 78 } 79 if(ans > n+m)printf("No solution"); 80 else cout << ans << endl; 81 }
然后这道题最后时限改成了2.5秒。我最慢的点跑了1.93+呢,,写的有点丑