A
直接将两个数组从小到大排序输出。
B
题意:是给你一个括号序列,里面由若干个
和若干个
,现在让你选若干子序列,这个子序列是偶数,前一半是
后一半是
,然后问你最少需要多少操作删除若干子序列后就不存在这样的序列。
思路:
答案只能为1或者0,因为子序列是形如
这种情况,所以我们双指针前后扫,一个(对应一个)。然后扫完后肯定就有这样的序列了。
C
题意:
给你一个序列,
,然后让你求
,但是由于结果可能很大,让你模一个
。
思路:
傻了。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
的范围很小,1000, 所以如果
的话,根据鸽笼原理,肯定会有两个
模
同余,那么结果肯定为0,否则直接算即可。
int a[N];
int main(){
int n = read(),m = read();
rep(i,1,n) a[i] = read();
if(n > m) return puts("0"),0;
ll ans = 1;
rep(i,1,n-1){
rep(j,i+1,n){
ans *= abs(a[i]-a[j]);
ans %= m;
}
}
cout <<ans;
}
D
交互题
给你一棵
个节点的树,然后你可以询问
次
节点的LCA,然后让你找出这颗树的根节点。
思路:
我们从每次询问叶子节点
,假如
是他们中的一个,则这个点必为根,否则,root的包含
的子树,和包含
的子树,都没有用了,删除掉即可。然后root的度-2,看root的度是否小于等于1,如果是,则将
也放进叶子节点的集合。知道剩余一个节点。
queue<int> lef;
int deg[N];
bool vis[N];
vector<int> G[N];
void dfs(int fa,int x,int root){//标记删除节点
vis[x] = 1;
for(int a:G[x]){
if(a!=fa&&a!=root) dfs(x,a,root);
}
}
int main(){
int n = read();
rep(i,1,n-1){
int u = read(),v = read();
deg[u] ++;deg[v] ++;
G[u].push_back(v);
G[v].push_back(u);
}
for(int i = 1;i <= n;++i){
if(deg[i]== 1) {lef.push(i);}
}
int a,b;
rep(i,1,n){
if(lef.size() == 1){
printf("! %d",lef.front());
return 0;
}
while(lef.size()&&vis[lef.front()]) lef.pop();
a = lef.front();lef.pop();
while(lef.size()&&vis[lef.front()]) lef.pop();
b = a;
if(lef.size()) {b = lef.front();lef.pop();}
if(a == b){
printf("! %d",a);
return 0;
}
printf("? %d %d\n",a,b);
fflush(stdout);
int root = read();
if(root == a||root == b){
printf("! %d",root);
return 0;
}
dfs(-1,a,root);dfs(-1,b,root);//删除子树
deg[root] -= 2;
if(deg[root] <=1) lef.push(root);
}
printf("! %d",lef.front());
}
E
题意:
给你一个
,和一个
,然后让你否造一个单增的序列
,使得存在
的对数是
。
思路:
首先,要知道存在
的序列可以使得满足题意的最多对数的序列,然后可以发现一个规律,长度为
的序列,最大对数为
依次递减2。很显然这是个等差数列,所以我们可以算出每一项,储存在
中。
如果
,则可以说明无解。
否则,我们找到小于等于
最大的一项
,
减去
,然后我们遍历前面已经确定下来的
数组,用
处理
,然后尝试确定其他位置的数。
int a[N];
int f[N];
map<int,int > hap;
int main(){
int n = read(),m = read();
rep(i,3,n){
int d = i - 2;
if(i&1) f[i] = (d+1)*(d+1)/4;
else f[i] = d * d/4 + d/2;
}
if(f[n] < m) return puts("-1"),0;
int i = 1;
while(i <= n&&f[i] <= m) {a[i] = i;i ++;}
i --;
m -= f[i];
if(m == 0){
rep(j,i+1,n) a[j] = a[j-1] + 5001;
}
else {
i ++;
int M = -1;
int pos = 1,tmp = -1;
rep(j,1,i-2)
rep(k,j+1,i-1) {hap[a[j]+a[k]] ++;M =max(M,a[j]+a[k]);}
rep(j,a[i-1]+1,M){
if(hap.count(j)&&hap[j] <= m){
m -= hap[j];
a[i++] = j;
//tmp = hap[j];
}
}
while(m--){
a[i] = a[i-1] + a[i-2];
i ++;
}
rep(j,i,n) a[j] = a[j-1] + 5001;
}
rep(j,1,n) printf("%d ",a[j]);
}
F