Codeforces AIM-TECH round div2
通过数 2(一题被叉掉) 447/5602
standing change:1869-1856、
Div1的D实在没心情写,找个时间再补吧
第四题动规,第五题……好吧不知道叫什么
A:
签到不解释
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
double s1, s2, v1, v2;
while(scanf("%lf%lf%lf%lf", &s1, &s2, &v1, &v2) != EOF){
double ans = (s2 - s1) / (v1 + v2);
printf("%.6f\n", ans);
}
return 0;
}
B:
Up处特判加错WA掉
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
#define LL long long
const int MAXN = 50;
LL a[MAXN];
int main()
{
int n;
while(scanf("%d", &n) != EOF){
LL ans = 0;
for(int i = 1 ; i <= n ; i++) scanf("%I64d", &a[i]);
sort(a + 1, a + 1 + n);
LL up = 1e9 + 5;
int ok = 1;
for(int i = n ; i >= 1 ; i--){
if(up < 0){
break;
}
a[i] = min(a[i], up);
ans += a[i];
up = min(up, a[i] - 1);
// printf("i = %d, up = %I64d\n", i, up);
}
if(ok)
printf("%I64d\n", ans);
else printf("0\n");
}
return 0;
}
C:
注意一下b的特殊性,就是和所有点都有连边
然后原集合最多划分成三个连通块,之后就随便写好了
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
const int MAXN = 500 + 5;
vector<int>lin[MAXN], col[5];
int g[MAXN][MAXN];
int degree[MAXN];
int color[MAXN];
int n, m;
int main()
{
while(scanf("%d%d", &n, &m) != EOF){
memset(g, 0, sizeof(g));
for(int i = 1 ; i <= 3 ; i++) col[i].clear();
for(int i = 1 ; i <= n ; i++) degree[i] = color[i] = 0, lin[i].clear();
for(int i = 0 ; i < m ; i++){
int u, v;
scanf("%d%d", &u, &v);
lin[u].push_back(v), lin[v].push_back(u);
degree[u]++, degree[v]++;
g[u][v] = g[v][u] = 1;
}
for(int i = 1 ; i <= n ; i++){
if(degree[i] == n - 1) color[i] = 2;
}
int f = 2;
int ok = 1;
for(int i = 1 ; i <= n ; i++){
if(color[i] == 0){
if(f){
int val = ((f == 2) ? 3 : 1);
color[i] = val;
col[val].push_back(i);
for(int j = 0 ; j < (int)lin[i].size() ; j++){
int v = lin[i][j];
// printf("val = %d, i = %d, v = %d\n", val, i, v);
if(color[v]) continue;
color[v] = val;
col[val].push_back(v);
}
f--;
}
else{
ok = 0;
break;
}
}
else if(color[i] != 2){
for(int j = 0 ; j < (int)lin[i].size() ; j++){
int v = lin[i][j];
if(color[v] != 2 && color[v] != color[i]){
ok = 0;
break;
}
}
}
}
if(ok){
for(int i = 1 ; i <= 3 ; i += 2){
for(int t1 = 0 ; t1 < (int)col[i].size() ; t1++){
for(int t2 = t1 + 1 ; t2 < (int)col[i].size() ; t2++){
int u = col[i][t1], v = col[i][t2];
// printf("u = %d, v = %d, i = %d\n", u, v, i);
if(g[u][v] == 0){
ok = 0;
break;
}
}
if(ok == 0) break;
}
if(ok == 0) break;
}
}
if(ok == 0) printf("No\n");
else{
printf("Yes\n");
for(int i = 1 ; i <= n ; i++){
printf("%c", 'a' + color[i] - 1);
}
printf("\n");
}
}
return 0;
}
D:
这题如果分类讨论做,那你就完了
因为最后得出的集合,肯定是以某个素数k为最小因子。所以我们可以枚举这个因子。因子的来源为(a[1],a[1]-1,a[1]+1),(a[n],a[n]-1,a[n]+1)(操作和不操作)
然后dp[i][j]表示第i个,j=0表示未操作,j=1表示操作中,j=2表示操作后。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
using namespace std;
#define LL long long
map<LL,int>mm;
const int MAXN = 1e6 + 5;
LL up;
int a[MAXN];
int n;
LL c1, c2;
LL dp[MAXN][5];
void MIN(LL &u, LL v)
{
if(u == -1 || u > v) u = v;
}
LL dfs(int v, int flag)
{
dp[0][1] = dp[0][2] = -1;
for(int i = 0 ; i < n ; i++){
// if(dp[i][0] == -1 && dp[i][1] == -1 && dp[i][2] == -1) return up + 1;
for(int j = 0 ; j < 3 ; j++) dp[i + 1][j] = -1;
// printf("i = %d, a[i] + flag = %d\n", i, a[i] + flag);
if(dp[i][0] != -1){
MIN(dp[i + 1][1], dp[i][0] + c1);
if(a[i + 1] % v == 0) MIN(dp[i + 1][0], dp[i][0]);
else if((a[i + 1] + 1) % v == 0 || ((a[i + 1] - 1) % v == 0)) MIN(dp[i + 1][0], dp[i][0] + c2);
}
if(dp[i][1] != -1){
MIN(dp[i + 1][1], dp[i][1] + c1);
if(a[i + 1] % v == 0) MIN(dp[i + 1][2], dp[i][1]);
else if((a[i + 1] + 1) % v == 0 || ((a[i + 1] - 1) % v == 0)) MIN(dp[i + 1][2], dp[i][1] + c2);
}
if(dp[i][2] != -1){
if(a[i + 1] % v == 0) MIN(dp[i + 1][2], dp[i][2]);
else if((a[i + 1] + 1) % v == 0 || ((a[i + 1] - 1) % v == 0)) MIN(dp[i + 1][2], dp[i][2] + c2);
}
}
LL temp = up + 1;
for(int i = 0 ; i < 3 ; i++) if(dp[n][i] != -1) temp = min(temp, dp[n][i]);
// if(v == 5 && flag == 1){
// printf("v = %d, flag = %d\n", v, flag);
// for(int j = 0 ; j < 3 ; j++){
// for(int i = 1 ; i <= n ; i++) printf("%I64d ", dp[i][j]);
// printf("\n");
// }
// system("pause");
// }
return temp;
}
//LL solve(int v, int flag)
//{
// LL ans = up + 1;
// for(int i = 2 ; i <= v ; i++){
// if(v % i == 0){
// ans = min(ans, dfs(i, flag));
// while(v % i == 0) v /= i;
// }
// }
// if(v > 1) ans = min(ans, dfs(v, flag));
//// printf("v = %d, flag = %d, ans = %I64d\n", v, flag, ans);
// return ans;
//}
int prime[MAXN * 10];
int cnt;
int vis[MAXN * 10];
vector<int>vc;
void init()
{
cnt = 0;
for(int i = 2 ; i < MAXN * 10 ; i++){
if(vis[i] == 0){
prime[cnt++] = i;
for(int now = i ; now < MAXN * 10 ; now += i){
vis[now] = 1;
}
}
}
}
void solve2(LL u)
{
for(int i = 0 ; i < cnt ; i++){
if(u % prime[i] == 0){
vis[i] = 1;
while(u % prime[i] == 0) u /= prime[i];
}
}
if(u > 1 && mm[u] == 0) vc.push_back(u), mm[u] = 1;
}
int main()
{
init();
while(scanf("%d%I64d%I64d", &n, &c1, &c2) != EOF){
for(int i = 1 ; i <= n ; i++) scanf("%d", &a[i]);
LL ans = c1 * (n - 1);
up = ans;
mm.clear();
vc.clear();
memset(vis, 0, sizeof(vis));
for(int i = -1 ; i <= 1 ; i++){
solve2(a[1] + i);
solve2(a[n] + i);
}
for(int i = 0 ; i < cnt ; i++){
if(vis[i]){
for(int j = -1 ; j <= 1 ; j++){
ans = min(ans, dfs(prime[i], j));
// printf("prime[i] = %d, j = %d, ans = %I64d\n", prime[i], j, ans);
}
}
}
for(int i = 0 ; i < (int)vc.size() ; i++){
for(int j = -1 ; j <= 1 ; j++){
ans = min(ans, dfs(vc[i], j));
// printf("vc[i] = %d, j = %d, ans = %I64d\n", vc[i], j, ans);
}
}
printf("%I64d\n", ans);
}
return 0;
}
/*
45 393296667 817784089
513035443 513035443 513035445 513035445 513035443 555648978 463549879 830693049 524420119 541365334 562791911 736173182 644390537 639730339 913702156 807631127 679411095 457747249 554394051 803981524 901463184 651788488 792766018 587562656 564169971 645381787 497940709 886010956 577261234 513035444 513035443 513035443 513035445 513035445 513035444 513035444 513035443 513035443 513035445 513035445 513035443 513035443 513035443 513035443 513035445
*/
E:
/*
这题改了三天……
刚开始以为是2SAT,好不容易调处来发现TLE
然后就用两点法做,但是由于单调性是不确定的,所以失败了
最终按照题解,二分答案判断是否正确
判断正确方法
把题目看成中间连续一段点分给x轴、其余点分给y轴
遍历所有点,对于当前点,用二分的答案来找到这个最右边点
**注意此处对于最右边点还有一个控制条件,就是它的横坐标绝对值小于等于当前遍历点,这样最后算不同轴上点距离时才不会出错
然后用预先处理好的前后缀得出此时最大最小纵坐标
找到一个合法即返回1
*/
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define LL long long
#define inf (200000001)
const int MAXN = 100000 + 5;
struct Point
{
LL x, y;
}d[MAXN];
bool cmp(Point u, Point v){return u.x < v.x;}
LL prefixmaxy[MAXN], prefixminy[MAXN];
LL suffixmaxy[MAXN], suffixminy[MAXN];
int n;
void init()
{
prefixmaxy[0] = suffixmaxy[n + 1] = -inf;
prefixminy[0] = suffixminy[n + 1] = inf;
for(int i = n ; i >= 1 ; i--){
suffixmaxy[i] = max(suffixmaxy[i + 1], d[i].y);
suffixminy[i] = min(suffixminy[i + 1], d[i].y);
}
for(int i = 1 ; i <= n ; i++){
prefixmaxy[i] = max(prefixmaxy[i - 1], d[i].y);
prefixminy[i] = min(prefixminy[i - 1], d[i].y);
}
}
LL sqr(LL u){return u * u;}
bool check(LL u)
{
sort(d + 1, d + 1 + n, cmp);
init();
if(sqr(d[n].x - d[1].x) <= u) return true;
if(sqr(prefixmaxy[n] - prefixminy[n]) <= u) return true;
int rear = 1;
for(int i = 1 ; i <= n ; i++){
while(i > rear) rear++;
while(rear < n && sqr(d[rear + 1].x - d[i].x) <= u && abs(d[i].x) >= abs(d[rear + 1].x)) rear++;
while(rear > i && abs(d[i].x) < abs(d[rear].x)) rear--; ///此处必须rear-1 LL miny, maxy; miny = min(prefixminy[i - 1], suffixminy[rear + 1]); maxy = max(prefixmaxy[i - 1], suffixmaxy[rear + 1]); LL tans = sqr(d[rear].x - d[i].x); tans = max(tans, sqr(maxy - miny)); tans = max(tans, max(sqr(d[rear].x), sqr(d[i].x)) + max(sqr(maxy), sqr(miny)) ); if(tans <= u) return true; } for(int i = 1 ; i <= n ; i++) d[i].x = -d[i].x; ///更改大小关系
sort(d + 1, d + 1 + n, cmp);
init();
rear = 1;
for(int i = 1 ; i <= n ; i++){
while(i > rear) rear++;
while(rear < n && sqr(d[rear + 1].x - d[i].x) <= u && abs(d[i].x) >= abs(d[rear + 1].x)) rear++;
while(rear > i && abs(d[i].x) < abs(d[rear].x)) rear--;
LL miny, maxy;
miny = min(prefixminy[i - 1], suffixminy[rear + 1]);
maxy = max(prefixmaxy[i - 1], suffixmaxy[rear + 1]);
LL tans = sqr(d[rear].x - d[i].x);
tans = max(tans, sqr(maxy - miny));
tans = max(tans, max(sqr(d[rear].x), sqr(d[i].x)) + max(sqr(maxy), sqr(miny)) );
if(tans <= u) return true;
}
return false;
}
int main()
{
while(scanf("%d", &n) != EOF){
for(int i = 1 ; i <= n ; i++) scanf("%I64d%I64d", &d[i].x, &d[i].y);
sort(d + 1, d + 1 + n, cmp);
if(n == 1){
printf("0\n");
continue;
}
LL le = 0, re = (LL)inf * inf;
while(le < re - 1){
LL mid = (le + re) >> 1;
if(check(mid)) re = mid;
else le = mid;
}
LL ans;
if(check(le)) ans = le;
else ans = re;
printf("%I64d\n", ans);
}
return 0;
}