#include<bits/stdc++.h>usingnamespace std;#defineintlonglong#definedoublelongdoubleusing i64 =longlong;typedef pair<int,int> PII;typedef pair<int,char> PIC;typedef pair<double,double> PDD;typedef pair<PII,int> PIII;typedef pair<int, pair<int,bool>> PIIB;typedef pair<PII, PII> PIIII;constint N =1e3+10;constint maxn =1e6;constint MAXN =100;constint mod =998244353;constint mod1 =954169327;constint mod2 =906097321;constint INF =0x3f3f3f3f3f3f3f3f;int dx[]={0,0,-1,1}, dy[]={1,-1,0,0};voidsolve(){int n, m; cin >> n >> m;
vector<string>g(n +1);for(int i =1; i <= n; i ++){
string s; cin >> s;
s =" "+ s;
g[i]= s;}int ans =0, idx =0;
vector<vector<int>>st(n +1,vector<int>(m +1));
vector<PII> pos;auto bfs =[&](int x,int y){
queue<PII> q;
q.push({x, y});
st[x][y]=++ idx;while(q.size()){auto t = q.front();
q.pop();int xx = t.first, yy = t.second;
pos.push_back({xx - x, yy - y});for(int i =0; i <4; i ++){int nx = xx + dx[i], ny = yy + dy[i];if(nx <=0|| nx > n || ny <=0|| ny > m)continue;if(st[nx][ny]|| g[nx][ny]!='.')continue;
st[nx][ny]= idx;
q.push({nx, ny});}}};for(int i =1; i <= n; i ++){for(int j =1; j <= m; j ++){if(st[i][j]|| g[i][j]!='.')continue;
pos.clear();bfs(i, j);bool flag =true;for(int r =1; r <= n && flag; r ++){for(int c =1; c <= m && flag; c ++){if(st[r][c]== idx || g[r][c]!='.')continue;bool ok =true;for(auto t : pos){int nx = r + t.first, ny = c + t.second;if(nx <=0|| nx > n || ny <=0|| ny > m || g[nx][ny]!='.'){
ok =false;break;}}if(ok) flag =false;}}if(flag) ans += pos.size();}}
cout << ans <<'\n';}signedmain(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);int t =1;
cin >> t;while(t--){solve();}return0;}
C - 原根(数论)
不会数学,抄一下队友的码
#include<iostream>#include<cstring>#include<cmath>#include<cstdio>#include<vector>#include<map>#include<algorithm>#include<queue>#include<iomanip>#include<random>usingnamespace std;typedeflonglong LL;typedef __int128 i128;typedefunsignedlonglong ULL;typedefdouble db;#defineintlonglongint n , m , p;voidAsuka(){
cin >> p >> m;if(m < p){int res =0;if((1^(p -1))<= m){
res ++;}if(((p +1)^(p -1))<= m)res ++;if(((p*2+1)^(p -1))<= m)res ++;
cout << res <<'\n';return;}int res =(m - p +1-2)/ p +1;// cout << res << '\n';int ans = res;for(int num = res * p +1;num <(res +3)* p +1;num += p){if((num ^(p -1))<= m)ans ++;}
cout << ans << endl;return;}signedmain(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);int t =1;
cin >> t;while(t --){Asuka();}return0;}
F - 等价重写(思维)
一开始提出一种很蠢的拓扑建图做法,然后队友说判断一下相邻两个能不能交换就好了,于是直接过了
#include<bits/stdc++.h>usingnamespace std;#defineintlonglong#definedoublelongdoubleusing i64 =longlong;typedef pair<int,int> PII;typedef pair<int,char> PIC;typedef pair<double,double> PDD;typedef pair<int, PII> PIII;typedef pair<int, pair<int,bool>> PIIB;constint N =1e5+10;constint maxn =1e6;constint MAXN =100;constint mod =998244353;constint mod1 =954169327;constint mod2 =906097321;constint INF =0x3f3f3f3f3f3f3f3f;voidsolve(){int n, m; cin >> n >> m;
vector<vector<int>>op(n +1);for(int i =1; i <= n; i ++){int x; cin >> x;while(x --){int pos; cin >> pos;
op[i].push_back(pos);}}
vector<bool>st(m +1);
vector<int>cnt(m +1);for(auto t : op[n]) cnt[t]++;bool flag =false;for(int i = n -1; i >=1; i --){bool flag =true;for(auto t : op[i]){if(st[t])continue;
cnt[t]++;if(cnt[t]>1) flag =false;}for(auto t : op[i +1]){if(st[t])continue;
cnt[t]--;
st[t]=true;}if(flag){
cout <<"Yes\n";for(int j =1; j <= i -1; j ++) cout << j <<' ';
cout << i +1<<' '<< i;for(int j = i +2; j <= n; j ++) cout <<' '<< j;
cout <<'\n';return;}}
cout <<"No\n";}signedmain(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);int t =1;
cin >> t;while(t--){solve();}return0;}
G - 背包(思维+01背包)
依次考虑前
i
i
i 个位置,对前
i
i
i 个位置 01背包,后面的免费取
k
k
k 个美丽值最大的
#include<bits/stdc++.h>usingnamespace std;#defineintlonglong#definedoublelongdoubleusing i64 =longlong;typedef pair<int,int> PII;typedef pair<int,char> PIC;typedef pair<double,double> PDD;typedef pair<int, PII> PIII;typedef pair<int, pair<int,bool>> PIIB;constint N =1010;constint maxn =1e6+10;constint mod =1e9+7;constint mod1 =954169327;constint mod2 =906097321;constint INF =0x3f3f3f3f3f3f3f3f;voidsolve(){int n, m, k; cin >> n >> m >> k;
vector<PII>a(n +1);for(int i =1; i <= n; i ++) cin >> a[i].first >> a[i].second;sort(a.begin()+1, a.end());
priority_queue<int, vector<int>, greater<int>> pq;
vector<int>g(n +2);
g[n +1]=0;int sum =0;for(int i = n; i >=1; i --){
sum += a[i].second;
pq.push(a[i].second);if(pq.size()> k){
sum -= pq.top();
pq.pop();}
g[i]= sum;}
vector<int>dp(m +1);int ans = g[1];for(int i =1; i <= n; i ++){for(int j = m; j >= a[i].first; j --){
dp[j]=max(dp[j], dp[j - a[i].first]+ a[i].second);
ans =max(ans, dp[j]+ g[i +1]);}}
cout << ans <<'\n';}signedmain(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);int t =1;// cin >> t;while(t--){solve();}}
I - 计数器(签到)
#include<bits/stdc++.h>usingnamespace std;#defineintlonglong#definedoublelongdoubleusing i64 =longlong;typedef pair<int,int> PII;typedef pair<int,char> PIC;typedef pair<double,double> PDD;typedef pair<int, PII> PIII;typedef pair<int, pair<int,bool>> PIIB;constint N =1e5+10;constint maxn =1e6;constint MAXN =100;constint mod =998244353;constint mod1 =954169327;constint mod2 =906097321;constint INF =0x3f3f3f3f3f3f3f3f;voidsolve(){int n, m; cin >> n >> m;
vector<PII>a(m +1);for(int i =1; i <= m; i ++) cin >> a[i].first >> a[i].second;sort(a.begin()+1, a.end());int num =0, op =0;for(int i =1; i <= m; i ++){int cnt = a[i].first - op;if(cnt ==0){if(num == a[i].second)continue;else{
cout <<"No\n";return;}}if(a[i].second ==0){
num =0;
op = a[i].first;}elseif(a[i].second <= cnt -1){
num = a[i].second;
op = a[i].first;}else{if(num + cnt == a[i].second){
num = a[i].second;
op = a[i].first;}else{
cout <<"No\n";return;}}}
cout <<"Yes\n";}signedmain(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);int t =1;
cin >> t;while(t--){solve();}return0;}
L - 电梯(贪心+模拟)
从高楼层往低楼层考虑,先放2的,放完了就放1的,放不满就考虑低楼层
#include<bits/stdc++.h>usingnamespace std;#defineintlonglong#definedoublelongdoubleusing i64 =longlong;typedef pair<int,int> PII;typedef pair<int,char> PIC;typedef pair<double,double> PDD;typedef pair<int, PII> PIII;typedef pair<int, pair<int,bool>> PIIB;constint N =1e5+10;constint maxn =1e6;constint MAXN =100;constint mod =998244353;constint mod1 =954169327;constint mod2 =906097321;constint INF =0x3f3f3f3f3f3f3f3f;int mp[N], ump[N];voidsolve(){int n, k; cin >> n >> k;
vector<int>c(n +1),w(n +1),f(n +1), tt;int maxx =0;for(int i =1; i <= n; i ++){
cin >> c[i]>> w[i]>> f[i];
tt.push_back(f[i]);}sort(tt.begin(), tt.end());
tt.erase(unique(tt.begin(), tt.end()), tt.end());for(int i =0; i < tt.size(); i ++){
mp[tt[i]]= i +1;
ump[i +1]= tt[i];}for(int i =1; i <= n; i ++){
f[i]= mp[f[i]];
maxx =max(maxx, f[i]);}
vector<vector<int>>cnt(maxx +1,vector<int>(3));for(int i =1; i <= n; i ++) cnt[f[i]][w[i]]+= c[i];int ans =0, yu =0;bool flag =false;for(int i = maxx; i >=1; i --){if(flag && cnt[i][1]!=0){
flag =false;
cnt[i][1]--;}if(yu !=0){int t1 = yu /2;// 放多少重量为2的if(cnt[i][2]>= t1){
cnt[i][2]-= t1;
yu %=2;}else{
yu -= cnt[i][2]*2;
cnt[i][2]=0;}if(yu !=0){if(cnt[i][1]>= yu){
cnt[i][1]-= yu;
yu =0;}else{
yu -= cnt[i][1];
cnt[i][1]=0;}}if(yu ==1){
yu =0;
flag =true;}}if(cnt[i][2]!=0)// 本楼层还有重量为2的{int tmp2 = k /2;// 一趟能运多少重量为2// 全是本楼层重量为2的int c1 = cnt[i][2]/ tmp2;
ans += c1 * ump[i];
cnt[i][2]%= tmp2;if(cnt[i][2]!=0){int wei = k - cnt[i][2]*2;// 还能装多少重量
cnt[i][2]=0;if(wei !=0){if(cnt[i][1]>= wei)// 剩下的部分全装本楼层重量为1的{
cnt[i][1]-= wei;
ans += ump[i];}else{
wei -= cnt[i][1];
cnt[i][1]=0;
yu += wei;
ans += ump[i];if(yu ==1){
yu =0;
flag =true;}}}}}if(cnt[i][1]!=0){int t = cnt[i][1]/ k;
ans += t * ump[i];
cnt[i][1]%= k;if(cnt[i][1]!=0){
ans += ump[i];
yu += k - cnt[i][1];
cnt[i][1]=0;}}}
cout << ans <<'\n';}signedmain(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);int t =1;
cin >> t;while(t--){solve();}return0;}
M - 接雨水(思维)
题目将原问题转化成了
∑
i
=
1
n
(
min
(
f
i
,
g
i
)
−
a
i
)
\sum\limits_{i = 1}^n \left( \min(f_i, g_i) - a_i \right)
i=1∑n(min(fi,gi)−ai) 我们知道
min
(
f
i
,
g
i
)
\min(f_i, g_i)
min(fi,gi) 可以转化成
f
i
+
g
i
−
max
a
i
f_i+g_i-\max{a_i}
fi+gi−maxai 所以我们要求的答案就是
∑
i
=
1
n
f
i
+
∑
i
=
1
n
g
i
−
n
×
max
a
i
−
∑
i
=
1
n
a
i
\sum\limits_{i = 1}^nf_i+\sum\limits_{i = 1}^ng_i-n\times \max{a_i-}\sum\limits_{i = 1}^na_i
i=1∑nfi+i=1∑ngi−n×maxai−i=1∑nai
n
×
max
a
i
n\times \max{a_i}
n×maxai 和
∑
i
=
1
n
a
i
\sum\limits_{i = 1}^na_i
i=1∑nai 很好求,问题就转化成了求
f
i
f_i
fi 和
g
i
g_i
gi
f
i
f_i
fi 被分成若干段,每一段的值都相同,且从左往右单调不减,所以我们可以用 set 维护,set 中记录每一段的开头下标和值,每次增加
a
i
a_i
ai 的值时,将
a
i
a_i
ai 后面小于
a
i
a_i
ai 的都删掉, 维护一下这个结构就可以了
#include<bits/stdc++.h>usingnamespace std;#defineintlonglong#definedoublelongdoubleusing i64 =longlong;typedef pair<int,int> PII;typedef pair<int,char> PIC;typedef pair<double,double> PDD;typedef pair<int, PII> PIII;typedef pair<int, pair<int,bool>> PIIB;constint N =1010;constint maxn =1e6+10;constint mod =1e9+7;constint mod1 =954169327;constint mod2 =906097321;constint INF =0x3f3f3f3f3f3f3f3f;voidsolve(){int n; cin >> n;
vector<int>a(n +1);
vector<int>ff(n +1),gg(n +1);int sum =0, maxx =0;for(int i =1; i <= n; i ++){
cin >> a[i];
maxx =max(maxx, a[i]);
sum += a[i];}auto add =[&](int pos,int x, set<PII>& st,int&sm, vector<int>&v){
v[pos]+= x;auto it =prev(st.upper_bound({pos, INF}));if((*it).second >= v[pos])return;
sm -=((*next(it)).first -(*it).first)*(*it).second;
sm +=(pos -(*it).first)*(*it).second +((*next(it)).first - pos)* v[pos];
it = st.insert({pos, v[pos]}).first;while((*next(it)).second <= v[pos]){
sm -=((*next(it)).first - pos)* v[pos]+((*next(next(it))).first -(*next(it)).first)*(*next(it)).second;
st.erase(next(it));
sm +=((*next(it)).first - pos)* v[pos];}};int smf =0, smg =0;
set<PII> f, g;
f.insert({1,0}), f.insert({n +1, INF});
g.insert({1,0}), g.insert({n +1, INF});for(int i =1; i <= n; i ++)add(i, a[i], f, smf, ff),add(n - i +1, a[i], g, smg, gg);int q; cin >> q;while(q --){int pos, x; cin >> pos >> x;
a[pos]+= x;
maxx =max(maxx, a[pos]);
sum += x;add(pos, x, f, smf, ff),add(n - pos +1, x, g, smg, gg);
cout << smf + smg - n * maxx - sum <<'\n';}}signedmain(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);int t =1;
cin >> t;while(t--){solve();}}