A. Colour the Flag
略
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
char a[100][100];
int main()
{
int t; cin >> t;
while(t--)
{
int n, m; cin >> n >> m;
string s;
int cnt = 0;
int fr = 2, fl = 2;
for(int i = 0; i < n; i++)
{
cin >> s;
for(int j = 0; j < m; j++)
if(s[j] == 'R') a[i][j] = 'R', fl = i&1, fr = j&1;
else if(s[j] == 'W') a[i][j] = s[j], fl = !(i&1), fr = j&1;
else a[i][j] = s[j];
}
int f = 0, fg = 1;
if(fr == fl && fr == 2) fl = 0, fr = 1;
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
if( ((i&1)==fl && (j&1)==fr) || ((i&1)==!fl && (j&1)==!fr) )
{
if(a[i][j] == 'W') { fg = 0; break; }
else a[i][j] = 'R';
}
else
{
if(a[i][j] == 'R') { fg = 0; break; }
a[i][j] = 'W';
}
}
if(fg == 0) break;
}
if(fg)
{
cout << "YES\n";
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
cout << a[i][j];
cout << endl;
}
}
else cout << "NO\n";
}
// system("pause");
}
B. Histogram Ugliness
分析:
只有一格宽的峰才有删掉的意义,差分即可.
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int a[400100];
int s[400100];
int main()
{
int t; cin >> t;
while(t--)
{
int n; cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i]; a[n+1] = 0;
for(int i = 1; i <= n+1; i++) s[i] = a[i]-a[i-1];
long long ans = 0, sum = -s[n+1];
for(int i = 1; i <= n; i++)
{
if(s[i]>=0 && s[i+1]<=0) ans += min(s[i],-s[i+1]);
sum += s[i]<0?-s[i]: s[i];
}
cout << sum - ans << endl;
}
// system("pause");
}
C. Little Alawn’s Puzzle
分析:
转换成一个n个点, 2n条无向边的图.
找连通块的个数.
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
const long long p = 1e9+7;
int a[3][400100];
int to[3][400100];
bool vis[400100];
map<int, int> mp;
int mypow(int x)
{
int rev = 1;
while(x--)
{
rev *= 2;
rev %= p;
}
return rev%p;
}
int main()
{
int t; cin >> t;
while(t--)
{
mp.clear();
int n; cin >> n;
for(int i = 1; i <= 2; i++)
for(int j = 1; j <= n; j++)
{
scanf("%d",&a[i][j]);
to[i==1?2:1][a[i][j]] = j;
vis[j] = 0;
}
int cnt = 0;
for(int i = 1, x = 1; i <= n; i++)
{
if(a[1][i] == a[2][i]) { cnt = -1; break; }
if(vis[a[1][i]]) continue;
vis[a[1][i]] = 1;
int j = i;
j = to[x][a[x][j]];
while(i != j)
{
vis[a[x][j]] = 1;
j = to[x][a[x][j]];
}
cnt++;
}
if(cnt == -1) printf("0\n");
else printf("%d\n",mypow(cnt));
}
// system("pause");
}
D. Lost Tree
每次询问, 距离为1的点肯定和距离为0的点有边.
容易想到每条边只需要有一个顶点被询问即可得到完整答案.
那么用第一次询问把图分层, 跑顶点数少的那一部分的全部顶点即可满足不超过
⌈
n
/
2
⌉
\lceil{n/2}\rceil
⌈n/2⌉的约束
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;
const int N = 2500;
vector<int> G[N];
void add(int u, int v)
{
G[u].push_back(v);
G[v].push_back(u);
}
int a[N];
int n;
bool f ;
bool vis[N];
bool pre(int x)
{
printf("? %d\n",x);
cout.flush();
int cnt1 = 0, cnt2 = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d",&a[i]);
if(a[i]&1==1) cnt1++, vis[i] = 1;
else cnt2++, vis[i] = 0;
if(a[i] == 1) add(x, i);
}
if(cnt1>=cnt2) return 1;
else return 0;
}
void query(int x)
{
printf("? %d\n",x);
cout.flush();
for(int i = 1; i <= n; i++)
{
scanf("%d",&a[i]);
if(a[i] == 1 && (i!=1))
{
add(x, i);
}
}
}
bool visited[N];
void dfs(int x, int fa)
{
if(visited[x]) return;
visited[x] = 1;
for(auto y: G[x])
{
if(y == fa) continue;
printf("%d %d\n",x,y);
dfs(y,x);
}
}
int main()
{
scanf("%d",&n);
if(pre(1)) f = 1;
else f = 0;
for(int i = 2; i <= n; i++)
if(f ^ vis[i]) query(i);
printf("!\n");
dfs(1, 0);
// system("pause");
}
昨晚卡D, 先是想了个假算法, 被自己造的数据hack掉了, 到最后二十分钟的时候想到正确思路, 电脑直接没电.
早上起来花二十分钟就过了.
属实阴间场.
掉大分💔.
说到底还是太菜.