热身赛
A.一定不会产生冲突,所以从1开始必定是最长的
bool vis[maxn];//这个位置标记取了
int main() {
IOS;
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; ++i){
ll j = i;
while(j <= n &&!vis[j]){//注意这里一定要先判j的大小,否则会段错误
cout << j << " ";
vis[j] = true;
j += k;
}
}
return 0;
}
B.
太难受了,自己写的一直找不出错误。
以后这么写吧…
需要记住的是最好在一开始就处理全局的;
再碰到 %n 的从1开始。
int val[maxn];//已ac
map<int, int> mp;
int sat[maxn];
int main() {
IOS;
int t;
cin >> t;
while(t--){
re(sat);
re(val);
mp.clear();
int n, k, m;
cin >> n >> k >> m;
for (int i = 1; i <= n; ++i){
cin >> val[i];
++mp[val[i]];//记下是奇数个
sat[i] = mp[val[i]];//赋给这一位
}
int kk = m % n;
for(int i = 1; i <= n; ++i){
int te = m / n;
if(m % n >= i)
++te;
if(mp[val[i]] % 2 == 0){
if(sat[i] % 2 != 0){
te = 0;
}
}
else {
if(sat[i] % 2 == 0)
te = (te + 1) / 2;//啊这是为什么啊
//懂了,要看这个数的位数和这个次数能不能对应
else
te = te / 2;
}
if(i == 1)
cout << te;
else
cout << " " << te;
}
cout << endl;
}
return 0;
}
还是第二种方法好懂。
分析了下,这个分类更细。
以后加不加可以写成 t += (n >= i)
int main() {
IOS;
int t;
cin >> t;
while(t--){
re(sat);
re(val);
mp.clear();
int n, k, m;
cin >> n >> k >> m;
for (int i = 1; i <= n; ++i){
cin >> val[i];
++mp[val[i]];//记下是奇数个
sat[i] = mp[val[i]];//赋给这一位
}
int na = m / n, nb = m % n;
for(int i = 1; i <= n; ++i){
int te = 0;
if(mp[val[i]] % 2 == 0){
if(sat[i] % 2)
te = 0;
else
te = na + (nb >= i);
}
else {
te = na / 2;
if(na % 2 == 0){
if(sat[i] % 2 == 0)
te += (nb >= i);
}
else {
if(sat[i] % 2)//一共奇个、奇数次、奇数位
te += (nb >= i);
else
++te;
}
}
if (i == 1)
cout << te;
else
cout << " " << te;
}
if(t >= 1)
cout << endl;
}
return 0;
}
C.
瞎推的,数据范围决定了显然不可能是一个一个试。
开始推的是只由最后一次决定,中间就算是负数也是越走越远。
50%wa后猜测第一次也许会更远,判了第一次后就过了
#define PII pair<int, int>
PII R = {1, 0}, U = {0, 1}, D = {0, -1}, L = {-1, 0};
int main() {
IOS;
int t;
cin >> t;
while(t--){
ll n, k;
cin >> n >> k;
string s;
cin >> s;
//我悟了,这个过程中的最大值
//只需要算最后一次的
ll x = 0, y = 0;
ll ans = abs(x) + abs(y);
for (int i = 0; i < n; ++i){
if(s[i] == 'R'){
x += R.first;
y += R.second;
}
else if(s[i] == 'U'){
x += U.first;
y += U.second;
}
else if(s[i] == 'D'){
x += D.first;
y += D.second;
}
else if(s[i] == 'L'){
x += L.first;
y += L.second;
}
ans = max(ans, abs(x) + abs(y));
}
x = (1ll) * x * (k - 1);
y = (1ll) * y * (k - 1);
ans = max(ans, abs(x) + abs(y));
for (int i = 0; i < n; ++i){
if(s[i] == 'R'){
x += R.first;
y += R.second;
}
else if(s[i] == 'U'){
x += U.first;
y += U.second;
}
else if(s[i] == 'D'){
x += D.first;
y += D.second;
}
else if(s[i] == 'L'){
x += L.first;
y += L.second;
}
ans = max(ans, abs(x) + abs(y));
}
cout << ans << endl;
}
return 0;
}
F.
题意又读假了,神奇的是看样例解释居然和读假的意思一样…
又去读了一次题,这题好难读懂绝对不是我英语差
啊不会
这个是最强最简洁的代码,很漂亮,直接找出了本质
这个挺容易理解的,就是判后模拟
知识点:
一个环如果分给其余的点,可推出最多n-1次不陷入死循环,大于n-1次即循环
或者说,无限循环时,有一个点被分成n-1份,有一个点被分成n-2份……那个n-1的点又能再被分为n-1(例3 2 1)
像有判 sum > n * (n - 2) 时就输出 Recurrent (大于n个n-2构成循环)
是因为最小的不会循环的数是 1 1 0,而像1 1 1,2 1 0等都会产生循环
优先队列可以自动排序,默认最大的永远在前面
他这个代码是判断出了最多n-1次,然后模拟,从大局出发的。
一直减n个(好算最终代价,直接加,不需要再判了)
这是一种好想法
#define re(a) memset((a), 0, sizeof((a)))
#define remax(a) memset((a), 0x3f3f3f3f, sizeof((a)))
#define PII pair<int, int>
int a[maxn];
int main() {
IOS;
int n;
cin >> n;
int sum = 0;
priority_queue<PII> q;
for (int i = 1; i <= n; ++i){
cin >> a[i];
sum += a[i];
q.push({a[i], i});
}
//if(sum > n * (n - 2)) {加了这个反而是错的,离谱哈,到时候再会过来看会错在哪。离谱,是爆int了,改成ll就过了
// cout << "Recurrent" << endl;
// return 0;
// }
for (int i = 0; i < n - 1; ++i){
PII temp = q.top();
q.pop();
if(temp.first + i < n - 1){
for (int j = 1; j <= n; ++j){
if(j == 1)
cout << a[j] + i;
else
cout << " " << a[j] + i;
}
cout << endl;
return 0;
}
a[temp.second] -= n;
q.push({a[temp.second], temp.second});
}
cout << "Recurrent" << endl;
return 0;
}
K.
澳门题好难,我好菜
看不懂样例;
下次如果在确认题没读错的情况下,如果思路对不上样例,很可能是题目含了什么算法,往怎么来的去考虑;如果这道题很多人做出来,
可以考虑先硬莽我判断错了变量,原来输出的是第几条边啊
Otherwise output k integers separated by a space in increasing order indicating the indices of the edges in the simple cycle with the smallest length.
这题有bfs和dfs两种输出方法,很不想写dfs,但是吧,基本题解看过去全是dfs;就题解而言,dfs的输出思路看得 也更清晰(虽然其实思路差不多)
BFS
判断有没有成环,看要连接的点是不是在同一个连通块,如果是,那么就已经成环了,很好证明
归根到底,还是对知识掌握得不熟悉;还有老是会跳着读!!!
照着标答也能错,麻了,v.clear()和v.pop_back()是不同的,会出错
DFS1
DFS2
#define re(a) memset((a), 0, sizeof((a)))
#define remax(a) memset((a), 0x3f3f3f3f, sizeof((a)))
#define PII pair<int, int>
int n, m;
PII e[maxn];
vector<PII> v[maxn];
int pre[maxn];
vector<int> ans;
bool vis[maxn];
void init(){
for (int i = 1; i <= n; ++i){
pre[i] = i;
v[i].clear();
}
re(e);
re(vis);
}
int find(int x){
if(pre[x] == x) return x;
return pre[x] = find(pre[x]);
}
bool dfs(int st, int en, int w){
if(st == en)
return true;
for(auto k : v[st]){
if(vis[k.first] || k.second >= w)
continue;
vis[k.first] = true;
if(dfs(k.first, en, w)){
ans.push_back(k.second);
return true;
}
}
return false;
}
int main() {
IOS;
int t;
cin >> t;
while(t--){
cin >> n >> m;
init();//这里的位置很重要,已经在这里错好几次了
for (int i = 1; i <= m; ++i){
int a, b;
cin >> a >> b;
e[i] = {a, b};
v[a].push_back({b, i});
v[b].push_back({a, i});
}
bool flag = true;
for (int i = 1; i <= m; ++i){
int u = e[i].first, v = e[i].second;
int x = find(u), y = find(v);
if(x == y){
ans.clear();
vis[u] = true;
dfs(u, v, i);
ans.push_back(i);
sort(ans.begin(), ans.end());
for(auto k : ans){
cout << k << " ";
}
cout << endl;
flag = false;
break;
}
else
pre[x] = y;
}
if(flag)
cout << -1 << endl;
}
return 0;
}
A.
这题很翻译了几次。
翻译的方法(读不懂下):一个句子一个句子翻,写在纸上,知道每个句子的意思
n行m列值为h
走过每个格子一次
上坡比下坡少
走相邻格
输出路径
实际上又少读了句子…
题解好简单,一读就会了。只要上比下小就行,大了就反过来
#define PII pair<int, int>
int g[1100][1100];
bool vis[1100][1100];
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
void init(){
re(g);
}
void solve(){
int n;
cin >> n;
init();
int cnt = 0;
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= n; ++j){
cin >> g[i][j];
}
}
vector<int> ans;
int pre = -1;
int cnt_up = 0, cnt_down = 0;
for (int i = 1; i <= n; ++i){
if(i & 1){
//直接顺着走
for (int j = 1; j <= n; ++j){
if(pre != -1){
if(pre > g[i][j])
++cnt_down;
else
++cnt_up;
}
ans.push_back(g[i][j]);
pre = g[i][j];
}
}
else {
for (int j = n; j >= 1; --j){
if(pre != -1){
if(pre > g[i][j])
++cnt_down;
else
++cnt_up;
}
ans.push_back(g[i][j]);
pre = g[i][j];
}
}
}
if(cnt_down < cnt_up){
reverse(ans.begin(), ans.end());
}
for(auto w : ans){
cout << w << " ";
}
}
int main() {
IOS;
// freopen("P1908_6.in","r",stdin);//读入数据
//freopen("P1908.out","w",stdout); //输出数据
int t;
cin >> t;
while(t--){
solve();
cout << endl;
}
return 0;
}
C.https://ac.nowcoder.com/acm/contest/31454/C
感觉挺简单的,学了再说吧
E.大意了,读题感觉挺简单的,交的人数也那么多
不愧是银牌题哈
涉及到了循环卷积、分块
佬的题解
//这过不了的,纪念一下
int p[maxn];
int mp[maxn];
int qq[maxn];
int qiu[maxn];
int res[maxn];
int main() {
IOS;
// freopen("P1908_6.in","r",stdin);//读入数据
// freopen("P1908.out","w",stdout); //输出数据
int n, q;
cin >> n >> q;
int ans = 0;
for (int i = 1; i <= n; ++i){
cin >> p[i];
qiu[p[i]] = i;
ans += (p[i] * i);
}
bool flag = false;
int cnt = 1;
res[0] = ans;
ans = 0;
for (int i = 1; i <= n; ++i){
ans += (qiu[i] * i);
//cout << qiu[i] << " ";
}
//cout << endl;
res[1] = ans;
while (!flag)
{
++cnt;
int temp[maxn];
memcpy(temp, qiu, sizeof(qiu));
for (int i = 1; i <= n; ++i)
{
temp[p[i]] = qiu[i];
}
// for (int i = 1; i <= n; ++i)
// {
// cout << temp[i] << " ";
// }
// cout << endl;
ans = 0;
for (int i = 1; i <= n; ++i)
{
ans += (temp[i] * i);
}
res[cnt] = ans;
memcpy(qiu, temp, sizeof(qiu));
int i;
for (i = 1; i <= n; ++i)
{
if (qiu[i] != i)
break;
}
if (i >= n)
flag = true;
}
for (int i = 1; i <= q; ++i){
int k;
cin >> k;
//直接处理循环节
cout << res[k % (n + 1)] << endl;
}
return 0;
}