序
掉了许多的 rating 终于涨了点。
A - Kuroni and the Gifts
此题做法显然,他告诉你不能有两个数之和是一样的,那么我们将两个序列从小至大排序,然后,输出即可
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
typedef long long ll;
#define get() getchar()
#define problem AC
#define inf 1r7
using namespace std;
const int Maxn = 10000;
int a[Maxn], b[Maxn], t, n;
int main() {
t = read();
while(t--) {
n = read();
for(int i = 1; i <= n; ++i) a[i] = read();
for(int i = 1; i <= n; ++i) b[i] = read();
sort(a + 1,a + 1 + n);
sort(b + 1,b + 1 + n);
for(int i = 1; i <= n; ++i) printf("%d ",a[i]);
printf("\n");
for(int i = 1; i <= n; ++i) printf("%d ",b[i]);
printf("\n");
}
return 0;
}
改了码风后,确实可读多了
B - Kuroni and Simple Strings
我们贪心的想,就从左到右扫,每一次去掉一个 simple 序列,想一想为什么
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
typedef long long ll;
#define get() getchar()
#define problem AC
#define inf 1r7
using namespace std;
const int Maxn = 1003;
int k, len, now,ans[Maxn][Maxn];
char c[Maxn];
bool flag[Maxn];
bool check(int k) {
int nowk =k + 1, sum = 0;
for(int l = 1, r = len; l <= len && l < r; ++l) {
if(flag[l]) continue;
if(c[l] == '('){
bool flag1 = 1;
for(; r>l; r--){
if(!flag[r] && c[r] == ')'){
flag1 = 0;
ans[nowk][++sum] = l;
ans[nowk][++sum] = r;
flag[l] = flag[r] =1;
break;
}
}
if(flag1) break;
}
}
ans[nowk][0] = sum;
sort(ans[nowk] + 1, ans[nowk] + 1 + sum);
return sum != 0;
}
int main() {
scanf("%s", c + 1);
len = strlen(c + 1);
for(int i = 1; i <= k; ++i) id[i] = i;
while(check(k)) k++;
printf("%d\n", k);
for(int i = 1; i <= k; ++i) {
printf("%d\n",ans[i][0]);
for(int j = 1;j <= ans[i][0]; ++j) {
printf("%d ", ans[i][j]);
}
printf("\n");
}
return 0;
}
更好的想,我们不妨记下每次的右指针。。。你懂的。
C - Kuroni and Impossible Calculation
此题真是大坑,注意观察数据范围。。
\[ 2 \le n \le 2\times 10^5, 2\le m \le 1000 \]
所以,他的答案是要求对于 m 取模,所以 若有一对 \(a_i,a_j\) 满足 \(|a_i-a_j|=km\) 于是答案就是零。。惊喜吗
若没有这样的。。就爆算吧。反正 \(n \le m \le 1000\)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
typedef long long ll;
#define get() getchar()
#define problem AC
#define inf 1r7
using namespace std;
const int Maxn = 2e5 + 11;
ll n, m, a[Maxn], b[Maxn], ans;
bool cmp(ll a, ll b) {
return a > b;
}
int main() {
n = read(); m = read();
for(int i = 1; i <= n; ++i) {
a[i] = read();
b[a[i]%m]++;
if(b[a[i]%m] > 1) {
printf("0");
return 0;
}
}
sort(a+1,a+1+n,cmp);
ans =1;
for(int i = 1;i<=n;i++){
for(int j= i+1;j<=n;j++){
ans =(ans *(a[i]-a[j]))%m;
}
}
printf("%lld", ans);
return 0;
}
事实上,没有比 \(O(n^2)\) 再优的了
D - Kuroni and the Celebration
此题要求我们求根,事实上,我们每次可以选择树的直径,询问直径的端点的最近公共祖先,就行了。
然后删去直径上,与 LCA 不一样的点,最后当只剩一个点时,就是我们的答案
#include <cstdio>
#include <cstring>
const int Maxn = 2009;
int n, h[Maxn], cnt, rt, jb, fa[Maxn], dep[Maxn];
bool vis[Maxn];
struct Edge {
int to, lac;
void insert(int x, int y) {to = y; lac = h[x]; h[x] = cnt++;}
}edge[Maxn];
void add_edge(int y, int x) {edge[cnt].insert(x, y); edge[cnt].insert(y, x);}
void dfs(int u) {
dep[u] = dep[fa[u]] + 1;
if(dep[u] > dep[jb]) jb = u;
for(int i = h[u]; i != -1; i = edge[i].lac) {
int to = edge[i].to;
if(vis[to] || to == fa[u]) continue;
fa[to] = u; dfs(to);
}
}
int main() {
n = read(); memset(h, -1, sizeof h);
for(int i = 1; i < n; ++i) add_edge(read(), read());
rt = 1;
while(1) {
jb = fa[rt] = 0; dfs(rt);
int t = jb; fa[t] = jb = 0; dfs(t);
if(t == rt && rt == jb) {
printf("! %d\n", rt);
fflush(stdout);
return 0;
}
printf("? %d %d\n", t, jb);
fflush(stdout);
rt = read();
for(int i = fa[jb]; i; i = fa[i]) vis[i] = 1;
vis[rt] = 0;
}
return 0;
}
嵬
庆祝人生第一道交互题