A. Minimum Integer
- 如果(d < l),则(d)满足条件
- 否则,输出(d * (r / d + 1))即可。
#include <cstdio>
#include <iostream>
using namespace std;
int main(){
int T; scanf("%d", &T);
while(T--){
int l, r, d; scanf("%d%d%d", &l, &r, &d);
if(d < l) printf("%d
", d);
else printf("%d
", d * (r / d + 1));
}
return 0;
}
B. Accordion
找到头尾的([:)和(:]),然后统计中间有几个(|)即可。
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int N = 500010;
int n;
char s[N];
int main(){
scanf("%s", s + 1);
n = strlen(s + 1);
int l = 1, r = n, cnt = 0;
while(l <= n && s[l] != '[') l++;
while(r && s[r] != ']') r--;
while(l <= n && s[l] != ':') l++;
while(r && s[r] != ':') r--;
if(l >= r) puts("-1");
else{
for(int i = l; i <= r; i++)
if(s[i] == '|') cnt++;
printf("%d
", 4 + cnt);
}
return 0;
}
C. Division and Union
发现可以竖着一条线将所有线分开成两部分,则两边任意选都可以。那么我们就可以找到这个条线。把线段按左端点排序,每次如果有交集就合并,没有交集,我们就找到了一个"断点"。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef pair<int, int> PII;
const int N = 100010;
int n, l[N], r[N];
PII a[N];
int main(){
int T; scanf("%d", &T);
while(T--){
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d%d", l + i, r + i);
a[i].first = l[i];
a[i].second = r[i];
}
sort(a + 1, a + 1 + n);
int rr = a[1].second, loc = 0;
for(int i = 2; i <= n; i++){
if(a[i].first <= rr)
rr = max(rr, a[i].second);
else { loc = rr; break; }
}
if(!loc) printf("-1");
else for(int i = 1; i <= n; i++)
if(r[i] <= rr) printf("1 ");
else printf("2 ");
puts("");
}
return 0;
}
D. GCD Counting
树形(dp),(100000)以内的每个数因子不超过(256)个(最多(2 ^ 3 * 3 * 5 * 7 * 9 * 13 * 19 > 100000))
首先把每个读入的权值质因数分解,两个数必须有质因子(gcd)才不会$ = 1(。存在一条边)(u, v)(,若)u(和)v$之间有相同的质因子则可以合并,但注意下一次合并必须也有这个质因子...
所以设计(f[i][j])为(i)个点为根节点,以第(j)个质因子为保障的最大长度。更新显然,如果遇到新的更新,答案可以更新,现在的 + 可以更新的。
所以... 虽然看似会炸掉,但是还是卡过了...
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
const int N = 200010;
int n, a[N], ans = 1;
vector<int> G[N], p[N], f[N];
bool success = true;
void dfs(int u, int last){
for(int i = 0; i < G[u].size(); i++){
int v = G[u][i];
if(v == last) continue;
dfs(v, u);
for(int j = 0; j < p[u].size(); j++){
for(int k = 0; k < p[v].size(); k++){
if(p[u][j] == p[v][k]){
ans = max(ans, f[u][j] + f[v][k]);
f[u][j] = max(f[u][j], f[v][k] + 1);
}
}
}
}
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", a + i);
if(a[i] != 1) success = false;
int x = a[i];
for(int j = 2; j * j <= a[i]; j++){
if(x % j == 0){
p[i].push_back(j);
f[i].push_back(1);
while(x % j == 0) x /= j;
}
}
if(x > 1) p[i].push_back(x), f[i].push_back(1);
}
for(int i = 1; i < n; i++){
int u, v; scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
if(success) puts("0");
else{
dfs(1, 0);
printf("%d", ans);
}
return 0;
}
E. Polycarp's New Job
两者都符合交换律,所以我们交换使得:
让(x <= y),(h <= w)。
维护(x)和(y)的最大值,(max\_x)和(max\_y)
检查$max_x <= h $ (&&) (max\_y <= w)即可。
显然,如果符合$max_y <= h $ (&&) (max\_x <= w),那么前者显然必然成立:
如果不符合,前者也有可能成立。
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 500010;
int n, a = 0, b = 0;
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++){
char ch; cin >> ch;
if(ch == '+'){
int x, y; scanf("%d%d", &x, &y);
if(x > y) swap(x, y);
a = max(a, x);
b = max(b, y);
}else{
int h, w; scanf("%d%d", &h, &w);
if(h > w) swap(h, w);
if(a <= h && b <= w) puts("YES");
else puts("NO");
}
}
return 0;
}