CF1270G Subset with Zero Sum
阿新 • • 發佈:2020-07-16
首先一定要從每個數的範圍 \(i - n \le a_i \le i - 1\) 入手,最開始是這樣一個想法,不難發現對於每個 \(i\) 都能選 \(n\) 個數,並且能選的右端點在 \(i - 1\),那麼我們可以吧每個 \(i\) 前移一位,實際上就是 \(0 \sim n - 1\) 這些位置上選沒選數,而如果這個位置上沒選那麼就一定選在了前面,實際上這樣還是非常不好做,於是我考慮只選擇了一個負數的情況,發現還是不能發現一種簡便的方法來找出這個集合,因此我們需要換一種方式思考。
既然分析性質行不通,我們可以考慮直接構造出答案。像這種找到一個集合滿足一些條件的題目,我們可以將其轉化為圖論問題,例如求一個連通塊的權值和為特定值或者找到一個環使得環上權值和為特定值,轉化方式就需要巧妙的連邊了。因為 \(a_i\)
#include<bits/stdc++.h>
using namespace std;
#define N 1000000 + 5
#define rep(i, l, r) for(int i = l; i <= r; ++i)
bool book[N];
int T, n, x, top, cnt, a[N], fa[N], st[N], ans[N];
int read(){
char c; int x = 0, f = 1;
c = getchar();
while(c > '9' || c < '0'){ if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int main(){
T = read();
while(T--){
n = read();
rep(i, 1, n) a[i] = read(), fa[i] = i - a[i];
x = 1, cnt = top = 0;
while(!book[x]) book[x] = true, st[++top] = x, x = fa[x];
while(st[top] != x) book[st[top]] = false, ans[++cnt] = st[top--];
ans[++cnt] = st[top];
while(top) book[st[top--]] = false;
printf("%d\n", cnt);
rep(i, 1, cnt) printf("%d ", ans[i]); puts("");
}
return 0;
}