牛客 牛牛的DRB迷宫II
题面:
思路:
code:
//https://ac.nowcoder.com/acm/contest/3004/B
#include<bits/stdc++.h>
using namespace std;
const int maxm=55;
char a[maxm][maxm];
signed main(){
int k;
cin>>k;
int n=30+2,m=30;
a[0][0]='B';//起点必须是B
for(int i=1;i<m;i++)a[0][i]='D';
for(int i=1;i<n-1;i++){
for(int j=0;j<m;j++){
if(j==i)a[i][j]='B';
else if(j==i-1)a[i][j]='R';
else a[i][j]='D';
}
}
for(int i=0;i<m;i++){
if(k>>i&1)a[i+1][i]='B';//如果这一位是1
a[n-1][i]='R';//最后一行都是R
}
a[n-1][m-1]='D';//终点随便哪个字符都行
cout<<n<<' '<<m<<endl;
for(int i=0;i<n;i++)cout<<a[i]<<endl;
return 0;
}
CodeForces 1088 C.Ehab and a 2-operation task
题意:
给一个长度为n的数组a,(0<=a(i)<=1e5)
你可以进行两种操作:
(1,i,x) 把1-i 的所有数加上x,x必须是非负数
(2,i,x) 把1-i 的所有数对x取模,x必须是整数
现在需要你构造出一组不超过n+1次的操作,使得进行完操作之后数组严格递增
思路:
先把所有数都加上1e5:a[i]+=1e5
然后对于从1到n的 i ,把1-i 取模 a[i]-i,这样之后a[i]就等于 i 了
结束之后的序列就是1-n,满足严格递增
ps:
假设一个数为x,那么我们可以通过选择x/2-x中的某个数k,使得x%k取模后的结果为0-x/2,即可以控制结果
code:
#include<bits/stdc++.h>
using namespace std;
const int maxm=2e5+5;
int a[maxm];
signed main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
cout<<n+1<<endl;
cout<<1<<' '<<n<<' '<<(int)1e5<<endl;
for(int i=1;i<=n;i++){
a[i]+=1e5;
}
for(int i=1;i<=n;i++){
cout<<2<<' '<<i<<' '<<a[i]-i<<endl;
}
return 0;
}
CodeForces 1017 C. The Phone Number
题意:
给定n,要求你构造一个1-n的排列,使得排列的LIS+LCS最小
思路:
错误思路:
开始想的是分成两块n/2的,然后前面(n/2+1)-n,后面1-n/2
发现n=9的时候就wa了
正确思路:
首先显然大的块放在前面小的块放在后面,例如34 12
假设分成p块,每块中的数连续且递增
则LIS=p,LCS=n/p
ans=p+n/p
又均值不等式得:p+n/p>=2sqrt(n),可推出当p等于sqrt(n)的时候p+n/p最小
因此取p=sqrt(n),分块输出即可
code:
#include<bits/stdc++.h>
using namespace std;
signed main(){
int n;
cin>>n;
int f=sqrt(n);
for(int i=n;i>=1;){
int now=max(i-f+1,1);
for(int j=now;j<=i;j++){
cout<<j<<' ';
}
i=now-1;
}
return 0;
}
CodeForces1278 E. Tests for problem D
题意:
给一颗n个顶点的树
要求构造出n个线段(l,r)
满足:
如果线段i和线段j相交,那么在点i和点j之间建立一条边,
要求建边之后的图就是给定的树
思路:
图中点2和点3都是点1的子节点,那么2和3的左端点都要大于1的左端点,右端点也要大于1的右端点
但是因为2和3的线段不能相交,因此:
如果2的左端点大于3的左端点
那么2的右端点小于3的右端点
如图,就是构造包含关系,子节点之间的两端大小比较是相反的(左边递增右边递减,或者反过来)
code:
#include<bits/stdc++.h>
using namespace std;
const int maxm=5e5+5;
int l[maxm],r[maxm],tot;
vector<int>g[maxm];
int n;
void dfs(int x,int fa){
int len=g[x].size();
for(int i=len-1;i>=0;i--){
int v=g[x][i];
if(v==fa)continue;
l[v]=++tot;
}
r[x]=++tot;
for(int i=0;i<len;i++){
int v=g[x][i];
if(v==fa)continue;
dfs(v,x);
}
}
signed main(){
scanf("%d",&n);
for(int i=1;i<n;i++){
int a,b;
scanf("%d%d",&a,&b);
g[a].push_back(b);
g[b].push_back(a);
}
l[1]=++tot;
dfs(1,-1);
for(int i=1;i<=n;i++){
printf("%d %d\n",l[i],r[i]);
}
return 0;
}
CodeForces1325 C. Ehab and Path-etic MEXs
题意:
给一颗n个顶点的树,要求在边权填上0-(n-2)
使得任意点对之间路径的mex最大值最小,输出一组方案
思路:
0和1不管怎么放肯定都在一条链上,接下来考虑2,如果2也在同一条链上,那么mex会变成3
所以要把2分开,做法是找到三个叶子节点填0、1、2,这样他们就不会再同一条链上了。
如果没有三个叶子,也就是树是一条链的话,不管怎么填mex都是n-1,不需要特判
因此找三个叶子填0、1、2,其他随便填填就行了,找叶子节点用度数就行了。
找一个度数为3的点,三个方向各填一个也可以。不过找叶子比这个方便。
CodeForces1328 D. Carousel
题意:
给定一个长度为n的数组a,这n个数围成一圈,
现在要你染色,满足当a(i)!=a(i-1)的时候,两者的颜色必须不同,
问最少要用多少种颜色,且输出一种染色方案
思路:
当所有a(i)相同的时候,全部染成一种颜色即可
当n为偶数的时候,染成1,2,1,2,1,2即可,这样首尾也是1,2
当n为奇数的时候,判断是否存在两个相邻的数,这两个相同,
如果存在,则答案为2,因为可以把这两个位置染成同一种颜色,类似将这两个点缩成一个点,
这样之后n就变成偶数了,继续1,2,1,2,即可
如果不存在,则答案为3,方案为1,2,1,2,…3,最后一个数放3即可。
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=2e5+5;
int a[maxm];
signed main(){
int T;
cin>>T;
while(T--){
int n;
cin>>n;
map<int,int>mark;
int ok=0;
for(int i=1;i<=n;i++){
cin>>a[i];
mark[a[i]]=1;
if(a[i]==a[i-1])ok=i;
}
if(a[1]==a[n])ok=1;
if(mark.size()==1){//只有一种
cout<<1<<endl;
for(int i=1;i<=n;i++)cout<<1<<' ';
}else if(n%2==0){//偶数情况
cout<<2<<endl;
for(int i=1;i<=n;i++){
cout<<i%2+1<<' ';
}
}else{//奇数情况
if(ok){//有相邻相同
cout<<2<<endl;
for(int i=1;i<=ok-1;i++){
cout<<i%2+1<<' ';
}
cout<<(ok-1)%2+1<<' ';
for(int i=ok+1;i<=n;i++){
cout<<(i-1)%2+1<<' ';
}
}else{//没有相邻相同
cout<<3<<endl;
for(int i=1;i<=n-1;i++){
cout<<i%2+1<<' ';
}
cout<<3<<' ';
}
}
cout<<endl;
}
return 0;
}