CodeForces Round #514 (div2)
A:Cashier
题意:问可以休息多少次。
代码:
#include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long long #define ULL unsigned LL #define fi first #define se second #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int inf = 0x3f3f3f3f; const int _inf = 0xc0c0c0c0; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL _INF = 0xc0c0c0c0c0c0c0c0; const LL mod = (int)1e9+7; const int N = 1e5 + 100; int n, L, a; int t[N], l[N]; int main(){ scanf("%d%d%d", &n, &L, &a); for(int i = 1; i <= n; ++i) scanf("%d%d", &t[i], &l[i]); t[n+1] = L; t[0] = l[0] = 0; int ans = 0; for(int i = 0; i <= n; ++i){ int dif = t[i+1] - t[i] - l[i]; ans += dif/a; } cout << ans << endl; return 0; }
题意:一次能给边上一圈填上'#',问这个图形合法不合法。填的时候不能越界。
直接去check行不行就好啦。
代码:
#include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long long #define ULL unsigned LL #define fi first #define se second #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int inf = 0x3f3f3f3f; const int _inf = 0xc0c0c0c0; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL _INF = 0xc0c0c0c0c0c0c0c0; const LL mod = (int)1e9+7; const int N = 1e3 + 100; char s[N][N]; int dx[8] = {0,0,0,1,1,2,2,2}; int dy[8] = {0,1,2,0,2,0,1,2}; int n, m; bool in(int x, int y){ if(x < 1 || x > n) return false; if(y < 1 || y > m) return false; return true; } bool check2(int x, int y){ for(int i = 0; i < 8; ++i){ int xx = x + dx[i]; int yy = y + dy[i]; if(!in(xx,yy) || s[xx][yy] != '#') return false; } return true; } bool check(int x, int y){ for(int b = 0; b < 8; ++b){ if(check2(x-dx[b], y-dy[b])) return true; } return false; } int main(){ scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i) scanf("%s", s[i]+1); for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j){ if(s[i][j] == '#'){ if(!check(i,j)){ puts("NO"); return 0; } } } puts("YES"); return 0; }
题意:给你[1,n]的数,每次会输出整个序列的gcd,然后可以删除一个数,然后问gcd的字典序排列最大是多少。
题解:发现 如果存在奇数,然后我们就会导致 gcd恒为1。 那么我们肯定是先删除奇数。
然后把奇数删完了之后,剩下了2,4,6,8,我们把这些数都/2,变成了新的1,2,3,4,然后再删除奇数就ok了。递归解决问题。
然后就是 如果出现了 1, 2, 3。 那么肯定是按照顺序删除 1 2 3最好了。
代码:
#include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long long #define ULL unsigned LL #define fi first #define se second #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int inf = 0x3f3f3f3f; const int _inf = 0xc0c0c0c0; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL _INF = 0xc0c0c0c0c0c0c0c0; const LL mod = (int)1e9+7; const int N = 1e5 + 100; int n; vector<int> vc; void dfs(int k, int n){ if(n == 0) return ; if(n == 3){ printf("%d %d %d", k, k, k*3); return ; } if(n == 1){ printf("%d ", k); return ; } if(n == 2){ printf("%d %d", k, 2*k); return ; } for(int i = 1; i <= n; i += 2){ printf("%d ", k); } dfs(k*2, n/2); } int main(){ scanf("%d", &n); dfs(1, n); return 0; }
题意:有n个保护动物,然后就是让你画一个○,使得所有的动物都在圈内,并且只有1个交点。
不是很想多讲,二分乱搞就好了,注意精度。
代码:
#include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long long #define ULL unsigned LL #define fi first #define se second #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int inf = 0x3f3f3f3f; const int _inf = 0xc0c0c0c0; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL _INF = 0xc0c0c0c0c0c0c0c0; const LL mod = (int)1e9+7; const int N = 1e5 + 100; pll p[N]; int n, f1 = 0, f2 = 0; double eps = 1e-9; bool check2(double x1, double y1, double x2, double y2){ long double len = y2; len *= len; long double dis = (long double)(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2); return len >= dis; } bool check(double len){ double lp = -1e7, rp = 1e7; for(int i = 1; i <= 100; ++i){ int lsz = 0, rsz = 0; double mid = (lp+rp) / 2; for(int k = 1; k <= n; ++k){ if(check2(p[k].fi,p[k].se,mid,len)); else if(p[k].fi <= mid ) lsz++; else rsz++; } if(lsz && rsz) return false; if(lsz+rsz == 0) return true; if(lsz) rp = mid; else lp = mid; } return false; } int main(){ scanf("%d", &n); for(int i = 1; i <= n; ++i){ scanf("%d%d", &p[i].fi, &p[i].se); if(p[i].se > 0) ++f1; else ++f2, p[i].se = -p[i].se; } if(f1 && f2){ puts("-1"); return 0; } double l = 0, r = 1e15; for(int i = 1; i <= 100; ++i){ double mid = (l+r)/2; if(check(mid)) r = mid; else l = mid; } printf("%.10f", r); return 0; }
题意:给定1棵以1为根的树,让你将这棵数分成竖着的几条链,问链最少是多少条,并且每一条链要求点的个数少于L,路径之和少于S。
题解:
从叶子网上爬,然后通过二分和倍增查看最多能到哪里,然后将这个点指到可以去的那个点为止。
然后不是叶子就接受叶子传上来的最远可以到哪里,如果到不了这个点就把这个点当做新的起点继续去找,如果可以到这个点就记录下最远可以去哪里就好了。
代码:
#include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long long #define ULL unsigned LL #define fi first #define se second #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int inf = 0x3f3f3f3f; const int _inf = 0xc0c0c0c0; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL _INF = 0xc0c0c0c0c0c0c0c0; const LL mod = (int)1e9+7; const int N = 1e5 + 100; int anc[N][20]; int a[N]; LL sum[N]; int n, l; LL S; vector<int> vc[N]; int deep[N]; void dfs(int o){ for(int x : vc[o]){ deep[x] = deep[o] + 1; sum[x] = sum[o] + a[x]; anc[x][0] = o; for(int i = 1; i < 19; ++i) anc[x][i] = anc[anc[x][i-1]][i-1]; dfs(x); } } int get(int o, int k){ for(int i = 19; i >= 0; --i){ if((k>>i)&1) o = anc[o][i]; } return o; } int to[N]; int ans; int Find(int o){ int ll = 1, rr = l; while(ll <= rr){ int mid = ll+rr >> 1; int p = get(o, mid); if(sum[o]-sum[p] <= S) ll = mid+1; else rr = mid-1; } return get(o, ll-1); } void solve(int o){ to[o] = -1; for(int x : vc[o]){ solve(x); if(to[x] == -1 || deep[to[x]] >= deep[o]) continue; if(to[o] == -1) to[o] = to[x]; else if(deep[to[o]] > deep[to[x]]) to[o] = to[x]; } if(to[o] == -1) ans++, to[o] = Find(o); } int main(){ scanf("%d%d%lld", &n, &l, &S); for(int i = 1; i <= n; ++i){ scanf("%d", &a[i]); if(a[i] > S){ puts("-1"); return 0; } } for(int i = 2,v; i <= n; ++i){ scanf("%d", &v); vc[v].pb(i); } sum[1] = a[1]; deep[1] = 1; dfs(1); solve(1); cout << ans << endl; return 0; }