2022NOIP A层联测35
好久之前的题了。
A. 弹珠游戏
任意时刻只能出现两种,出现第三种时优先匹配剩下两种的组合,再考虑形成新的组合,匹配啥是一样的,于是每次乘上方案数
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
int read(){
int x = 0; char c = getchar();
while(!isdigit(c))c = getchar();
do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
return x;
}
const int mod = 998244353;
const int maxn = 600005;
int n, ans;
string s;
map <string, int>f;
int main(){
freopen("A.in","r",stdin);
freopen("A.out","w",stdout);
cin >> n >> s;
n = n * 3;
f[s.substr(0, 1)] = ans = 1;
for(int i = 1; i < n; ++i)
if(s[i] == 'R'){
if(f["GB"]){ans = 1ll * ans * f["GB"] % mod; --f["GB"]; continue;}
if(f["G"]){ans = 1ll * ans * f["G"] % mod; --f["G"]; ++f["RG"]; continue;}
if(f["B"]){ans = 1ll * ans * f["B"] % mod; --f["B"]; ++f["RB"]; continue;}
++f["R"];
}else if(s[i] == 'G'){
if(f["RB"]){ans = 1ll * ans * f["RB"] % mod; --f["RB"]; continue;}
if(f["R"]){ans = 1ll * ans * f["R"] % mod; --f["R"]; ++f["RG"]; continue;}
if(f["B"]){ans = 1ll * ans * f["B"] % mod; --f["B"]; ++f["GB"]; continue;}
++f["G"];
}else{
if(f["RG"]){ans = 1ll * ans * f["RG"] % mod; --f["RG"]; continue;}
if(f["R"]){ans = 1ll * ans * f["R"] % mod; --f["R"]; ++f["RB"]; continue;}
if(f["G"]){ans = 1ll * ans * f["G"] % mod; --f["G"]; ++f["GB"]; continue;}
++f["B"];
}
for(int i = 1; i <= n / 3; ++i)ans = 1ll * ans * i % mod;
cout << ans << endl;
return 0;
}
B. 晚会
建立一棵生成树,考虑非树边
发现合法情况会形成类似等腰三角形的情况并且底边长要大于等于腰长
那么建立最大生成树,判断时查询路径最小值,合法情况下等于当前非树边边权
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
int read(){
int x = 0; char c = getchar();
while(!isdigit(c))c = getchar();
do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
return x;
}
int n, m;
const int maxn = 600005;
struct DSU{
int f[maxn];
void init(){for(int i = 1; i <= n + n; ++i)f[i] = i;}
int fa(int x){return f[x] == x ? x : f[x] = fa(f[x]);}
}S;
struct EDGE{
int u, v, w;
friend bool operator < (const EDGE &x, const EDGE &y){
return x.w > y.w;
}
}E[maxn];
int cnt, val[maxn];
vector<int>g[maxn];
int dep[maxn], son[maxn], fa[maxn], siz[maxn], top[maxn], leaf[maxn];
void dfs(int x){
siz[x] = 1;if(x <= n)leaf[x] = 1;
for(int v : g[x]){
fa[v] = x; dep[v] = dep[x] + 1;
dfs(v);
leaf[x] += leaf[v];
siz[x] += siz[v]; son[x] = siz[son[x]] > siz[v] ? son[x] : v;
}
}
void dfs2(int x, int tp){
top[x] = tp;
if(son[x])dfs2(son[x], tp);
for(int v : g[x])if(v != son[x])dfs2(v, v);
}
int lca(int x, int y){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]])swap(x, y);
x = fa[top[x]];
}
return dep[x] < dep[y] ? x : y;
}
vector <int> notree;
bool check(){
for(int i : notree){
if(val[lca(E[i].u, E[i].v)] != E[i].w)return false;
}
return true;
}
ll ans;
void solve(int x){
if(x <= n)return;
int sil = 0, sir = 0;
for(int v : g[x]){
solve(v);
if(sil) sir = leaf[v];
else sil = leaf[v];
}
ans = ans - 1ll * sil * sir + 1ll * sil * sir * val[x];
}
ll sol(){
ans = 1ll * n * (n - 1) / 2;
for(int i = cnt; i >= 1; --i)if(!fa[i])solve(i);
return ans;
}
int main(){
freopen("B.in","r",stdin);
freopen("B.out","w",stdout);
n = read(), m = read(); S.init();
for(int i = 1; i <= m; ++i)E[i].u = read(), E[i].v = read(), E[i].w = read();
sort(E + 1, E + m + 1); cnt = n;
for(int i = 1; i <= m; ++i)if(S.fa(E[i].u) != S.fa(E[i].v)){
int u = S.fa(E[i].u), v = S.fa(E[i].v);
val[++cnt] = E[i].w;
g[cnt].push_back(u);
g[cnt].push_back(v);
S.f[u] = S.f[v] = cnt;
}else notree.push_back(i);
for(int i = cnt; i >= 1; --i)if(!siz[i])dfs(i), dfs2(i, i);
if(check())printf("%lld\n",sol());
else printf("-1\n");
return 0;
}
C. 优美的字符串
DP 套 DP
D. 选举
回滚莫队+分块
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
int read(){
int x = 0; char c = getchar();
while(!isdigit(c))c = getchar();
do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
return x;
}
const int maxn = 300005;
int n, m, Q;
int len, bl[maxn];
int lem, bm[maxn];
int a[maxn], b[maxn];
struct node{
int l, r, ql, qr, id;
friend bool operator < (const node &x, const node &y){
return bl[x.l] == bl[y.l] ? x.r < y.r : x.l < y.l;
}
}q[maxn];
ll cnt[maxn], ans[maxn], mx[maxn], rem[maxn];
void Ckmx(ll &x, ll y){if(y > x)x = y;}
void Add(int pos){
cnt[a[pos]] += b[pos];
rem[pos] = mx[bm[a[pos]]];
Ckmx(mx[bm[a[pos]]], cnt[a[pos]]);
}
void Del(int pos){
cnt[a[pos]] -= b[pos];
mx[bm[a[pos]]] = rem[pos];
}
void clear(int r){
while(r && cnt[a[r]] > 0){
mx[bm[a[r]]] = 0;
cnt[a[r]] -= b[r];
--r;
}
}
ll query(int l, int r){
ll ans = 0;
if(bm[l] == bm[r]){
for(int i = l; i <= r; ++i)Ckmx(ans, cnt[i]);
return ans;
}
for(int i = bm[l] * lem; i >= l; --i)Ckmx(ans, cnt[i]);
for(int i = (bm[r] - 1) * lem + 1; i <= r; ++i)Ckmx(ans, cnt[i]);
for(int i = bm[l] + 1; i < bm[r]; ++i)Ckmx(ans, mx[i]);
return ans;
}
void sol(){
int r = 0;
for(int i = 1; i <= Q; ++i){
if(bl[q[i].l] != bl[q[i - 1].l]){clear(r); r = min(bl[q[i].l] * len, n);}
while(r < q[i].r)Add(++r);
int up = min(q[i].r, bl[q[i].l] * len);
for(int j = q[i].l; j <= up; ++j)Add(j);
ans[q[i].id] = query(q[i].ql, q[i].qr);
for(int j = up; j >= q[i].l; --j)Del(j);
}
}
int main(){
freopen("D.in","r",stdin);
freopen("D.out","w",stdout);
n = read(), m = read(), Q = read();
for(int i = 1; i <= n; ++i)a[i] = read();
for(int i = 1; i <= n; ++i)b[i] = read();
for(int i = 1; i <= Q; ++i){
q[i].l = read(), q[i].r = read();
q[i].ql = read(), q[i].qr = read();
q[i].id = i;
}
len = sqrt(n); for(int i = 1; i <= n; ++i)bl[i] = (i + len - 1) / len;
lem = sqrt(m); for(int i = 1; i <= m; ++i)bm[i] = (i + lem - 1) / lem;
sort(q + 1, q + Q + 1); sol();
for(int i = 1; i <= Q; ++i)printf("%lld\n",ans[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】