Codeforces Round 686 (Div. 3)
A. Special Permutation
#include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=1e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const double eps=1e-6;
void solve() {
int n;cin>>n;
cout<<n<<' ';
for(int i=1;i<n;++i)cout<<i<<' ';
cout<<'\n';
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T=1;
cin>>T;
// init();
while(T--){
solve();
}
return 0;
}
B. Unique Bid Auction
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i32 = int32_t;
using pii = pair<int, int>;
using vi = vector<int>;
const int inf = 1e18;
void solve() {
int n;
cin >> n;
map<int, int> cnt;
for (int i = 1, x; i <= n; i++) {
cin >> x;
if (cnt[x] == 0) cnt[x] = i;
else cnt[x] = -1;
}
for (auto [k, v]: cnt) {
if (v == -1) continue;
cout << v << "\n";
return;
}
cout << "-1\n";
return;
}
i32 main() {
int TC;
for (cin >> TC; TC; TC--)
solve();
return 0;
}
C. Sequence Transformation
我们分别统计出相同的每一种数字的位置,然后枚举保留那些数字,这些数字会把序列分层若干段,统计一下非空段的数量即。
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i32 = int32_t;
using pii = pair<int, int>;
using vi = vector<int>;
const int inf = 1e18;
const int A = 2e5;
void solve() {
int n;
cin >> n;
int res = inf;
map<int, vi> cnt;
for (int i = 1, x; i <= n; i++) {
cin >> x;
if (cnt[x].empty()) cnt[x].push_back(0);
cnt[x].push_back(i);
}
for (auto [k, v]: cnt) {
int ans = 0;
v.push_back(n + 1);
for (int i = 1; i < v.size(); i++)
ans += (v[i] - v[i - 1]) > 1;
res = min(res, ans);
}
cout << res << "\n";
}
i32 main() {
int TC;
for (cin >> TC; TC; TC--)
solve();
return 0;
}
D. Number into Sequence
质因数分解一下,然后找到最高次项的因子,次方数就是\(k\),然后把其他因子都乘到任意一个数字上就好。
#include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=1e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const double eps=1e-6;
void solve() {
int n,m;cin>>n;
m=n;
int c=0,ma;
for(int i=2,cnt;i*i<=n;++i){
if(n%i)continue;
cnt=0;
while(n%i==0)cnt++,n/=i;
if(cnt>c)ma=i,c=cnt;
}
if(n>1)
if(1>c)ma=n,c=1;
for(int i=0;i<c-1;++i)m/=ma;
cout<<c<<'\n';
for(int i=0;i<c-1;++i)cout<<ma<<' ';
cout<<m<<'\n';
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T=1;
cin>>T;
// init();
while(T--){
solve();
}
return 0;
}
E. Number of Simple Paths
图是一个基环树,找到基环树上所有的点,然后把环上的边都删掉,这样就会形成若干个森林。
\(u\)是的点,统计出\(u\)的子树大小\(cnt[u]\)。
然后现在分情况讨论,对于两个点\(x,y\)之间在基环树上有多少个简单路径。
- 两个点在一个子树内,在基环树上只有一个简单路径
- 两个点不在一个子树内,在基环树上只有两个简单路径
所以我们对于每一个环上的点来考虑,对于两个点都在子树则\(C_{cnt[u]}^2\),如果其中一个点在子树内,另一个点不在,则\(2cnt[x]\times(n-cnt[x])\),对于这种情况,每对点会枚举两次,所以还要除以 2
#include<bits/stdc++.h>
using namespace std;
#define int long long
using i32 = int32_t;
using vi = vector<i32>;
using vI = vector<int>;
void solve() {
i32 n;
cin >> n;
vector e(n + 1, vi());
vi inDeg(n + 1);
for (int i = 0, u, v; i < n; ++i) {
cin >> u >> v;
inDeg[u]++, inDeg[v]++;
e[u].push_back(v), e[v].push_back(u);
}
// 拓扑
vector<bool> visH(n + 1);
queue<i32> q;
for (i32 i = 1; i <= n; ++i)
if (inDeg[i] == 1) q.push(i);
for (i32 u; not q.empty();) {
u = q.front(), q.pop();
visH[u] = true;
for (auto v: e[u])
if (--inDeg[v] == 1)q.push(v);
}
int ans = 0;
for (int i = 1, omg; i <= n; ++i) {
if (visH[i])continue; // 不在环上
vector<bool> vis(n + 1);
omg = 0;
queue<i32> que;
que.push(i);
for (int u; not que.empty();) {
u = que.front(), que.pop(), omg++;
vis[u] = true;
for (auto y: e[u]) {
if (visH[y] == false or vis[y] == true) continue;
que.push(y);
}
}
ans += omg * (omg - 1ll) / 2ll + (n - omg) * omg;
}
cout << ans << '\n';
return;
}
i32 main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
i32 TC;
for (cin >> TC; TC; TC--)
solve();
return 0;
}
F. Array Partition
首先可以知道的是对于一个区间,如果确定了区间的一个端点,区间的最值是单调的。所以可以提前预处理出前缀后缀的最大值。然后枚举\(x\),去二分\(y\)。在二分的过程中需要知道区间的的最小值,所以套一个\(ST\)表就好。
#include<bits/stdc++.h>
using namespace std;
#define int long long
using i32 = int32_t;
using vi = vector<int>;
const int N = 2e5, logN = log2(N) + 1;
vi log_2(N);
void init() {
log_2[0] = -1;
for (int i = 1; i < N; i++)
log_2[i] = log_2[i >> 1] + 1;
return;
}
struct ST {
vector<vi> f;
ST(const vi &a) {
f = vector(a.size(), vi(logN + 1));
for (int i = 1; i < a.size(); i++)
f[i][0] = a[i];
for (int j = 1; j <= logN; j++)
for (int i = 1; i + (1 << j) - 1 < a.size(); i++)
f[i][j] = min(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
}
int query(int l, int r) {
int s = log_2[r - l + 1];
return min(f[l][s], f[r - (1 << s) + 1][s]);
}
};
void solve() {
int n;
cin >> n;
vi a(n + 1);
for (int i = 1; i <= n; i++) cin >> a[i];
vi pre(n + 1), suf(n + 2);
for (int i = 1; i <= n; i++)
pre[i] = max(pre[i - 1], a[i]);
for (int i = n; i >= 1; i--)
suf[i] = max(suf[i + 1], a[i]);
ST s(a);
for (int i = 1, l, r, mid; i <= n; i++) {
l = i+1, r = n;
for (int mid, val; l <= r;) {
mid = (l + r) / 2, val = s.query(i + 1, mid);
if (pre[i] == val and val == suf[mid + 1]) {
cout << "YES\n" << i << " " << mid - i << " " << n - mid << "\n";
return;
} else if (val > pre[i]) {
l = mid + 1;
} else if (val < pre[i]) {
r = mid - 1;
} else {
if (val < suf[mid + 1]) l = mid + 1;
else r = mid - 1;
}
}
}
cout << "NO\n";
return;
}
i32 main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
init();
int TC;
for (cin >> TC; TC; TC--)
solve();
return 0;
}