The 2025 ICPC Latin America Championship2025/3/26组队vp记录
比赛链接:https://codeforces.com/gym/105789
A.Ananna
思路:如果从端点去枚举一条路构成回文串会TLE,所以想着枚举中心向着两边扩散,如果两个端点构成了回文串(最多n*n对),那么他们扩散就只要看字符相同即可,所以建正边和反边。先把所有边塞进队列,然后把每个
点作为点对也塞进队列(比如2——3——4情况需要这样扩散),左点跑反边,右边跑正边即可。
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
inline ll read()
{
register ll x = 0, f = 1;
char c = getchar();
while (c < '0' || c>'9')
{
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
c = getchar();
}
return x * f;
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
struct ss
{
ll l, r;
friend bool operator<(const ss& a, const ss& b)
{
return a.l < b.l;
}
};
bool vis[5005][5005], dd[5005][5005];
vector<pair<ll,char>>g1[5005];
vector<pair<ll,char>>g2[5005];
int main()
{
fio();
ll n, m;
cin >> n >> m;
queue<ss>f;
map<pair<ll,pair<ll,char>>,bool>mp;
for (ll i = 1; i <= m; i++)
{
ll l, r;
char k;
cin >> l >> r >> k;
if(mp[{l,{r,k}}]==1)continue;
else mp[{l,{r,k}}]=1;
g1[l].push_back({r,k});
g2[r].push_back({l,k});
if (l != r&&dd[l][r]==0)
{
f.push({l,r});
dd[l][r]=1;
}
}
for(ll j=1;j<=n;j++)
{
f.push({j,j});
dd[j][j]=1;
}
ll ans = 0;
while (!f.empty())
{
ll l = f.front().l;
ll r = f.front().r;
f.pop();
if (vis[l][r])continue;
vis[l][r] = 1;
if(l!=r){
ans++;
}
for (auto j : g2[l])
{
for (auto k : g1[r])
{
if (j.first == k.first || vis[j.first][k.first] || j.second!=k.second || dd[j.first][k.first])continue;
f.push({ j.first,k.first }), dd[j.first][k.first] = 1;
}
}
}
cout << ans << endl;
}
C. Coatless in Yakutsk
思路:队友写的,二分
#include <iostream>
#include <algorithm>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#include <numeric>
#define endl '\n'
#define ll long long
using namespace std;
const ll N=2e5+5;
int c,n;
int a[N];
bool check(int x){
int day=0;
for(int i=1;i<=n;i++){
if(day>c)return 0;
if(a[i]>=x){
day=0;
}else{
day++;
}
}
if(day>c)return 0;
return 1;
}
void eachT()
{
cin>>c>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int l=-50,r=50,mid,ans;
while(l<=r){
mid=(l+r)/2;
if(check(mid)){
l=mid+1;
ans=mid;
}else{
r=mid-1;
}
}
cout<<ans<<"\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
ll T=1;
// cin>>T;
while(T--)
eachT();
}
G. Game of Pieces
思路:要么动态开点线段树或者离散化线段树,要么set维护
//#注意如果多组样例,记得手动更新p数组,然后rt归位,在更新和询问时query都是必须判断有没开过点的的,只需q*logn的空间
#include<iostream>
#define ll long long
using namespace std;
const ll maxn = 5e6 + 10;
struct s
{
ll l = -1, r = -1;
ll v, v1=0,v2=0,la = -1;
}p[maxn << 2];
ll rt = -1;
ll root = -1;
void push_down(ll pos, ll l, ll r)
{
if (p[pos].la >= 0)
{
if (p[pos].l == -1)p[pos].l = ++rt;
if (p[pos].r == -1)p[pos].r = ++rt;
ll mid = (l + r) >> 1;
// p[p[pos].l].v += (mid - l + 1) * p[pos].la;//区间值
// p[p[pos].r].v += (r - mid) * p[pos].la;//区间值
p[p[pos].l].v1 += p[pos].la;
p[p[pos].r].v1 += p[pos].la;
p[p[pos].l].v2 += p[pos].la;
p[p[pos].r].v2 += p[pos].la;
p[pos].v1 = max(p[p[pos].l].v1, p[p[pos].r].v1);
p[pos].v2 = min(p[p[pos].l].v2, p[p[pos].r].v2);
p[p[pos].l].la = (p[p[pos].l].la == -1 ? p[pos].la : p[pos].la + p[p[pos].l].la);
p[p[pos].r].la = (p[p[pos].r].la == -1 ? p[pos].la : p[pos].la + p[p[pos].r].la);
p[pos].la = -1;
}
}
void update(ll& pos, ll l1, ll r1, ll l, ll r, ll v)
{
if (pos < 0)pos = ++rt;
if (l1 == l && r1 == r)
{
//p[pos].v += (r - l + 1) * v;
p[pos].la = (p[pos].la == -1 ? v : p[pos].la + v);
p[pos].v1+=v;
p[pos].v2+=v;
return;
}
push_down(pos, l1, r1);
ll mid = (l1 + r1) >> 1;
if (l <= mid)
update(p[pos].l, l1, mid, l, min(r, mid), v);
if (r >= mid + 1)
update(p[pos].r, mid + 1, r1, max(mid + 1, l), r, v);
// p[pos].v = (p[pos].l >= 0 ? p[p[pos].l].v : 0) + (p[pos].r >= 0 ? p[p[pos].r].v : 0);
p[pos].v1 = max((p[pos].l >= 0 ? p[p[pos].l].v1 : 0), (p[pos].r >= 0 ? p[p[pos].r].v1 : 0));
p[pos].v2 = min((p[pos].l >= 0 ? p[p[pos].l].v2 : 0), (p[pos].r >= 0 ? p[p[pos].r].v2 : 0));
}
pair<ll,ll> query(ll& pos, ll l1, ll r1, ll l, ll r)
{
pair<ll, ll> ans = { 0,1e18 };
if (pos < 0)pos = ++rt;
if (l1 == l && r1 == r)
{
return {p[pos].v1,p[pos].v2};
}
push_down(pos, l1, r1);
ll mid = (l1 + r1) >> 1;
pair<ll, ll>z;
if (l <= mid)
{
z = query(p[pos].l, l1, mid, l, min(r, mid));
ans.first =max(z.first,ans.first);
ans.second=min(ans.second, z.second);
}
if (r >= mid + 1)
{
z = query(p[pos].r, mid + 1, r1, max(mid + 1, l), r);
ans.first =max(z.first,ans.first);
ans.second=min(ans.second, z.second);
}
return ans;
}
int main()
{
ll n;
cin >> n;
ll yb = 2e18;
while (n--)
{
char f;
ll l, r;
cin >> f >> l >> r;
if (f == '|')
{
cout << "S";
update(root, 1, yb, r, r, l);
}
else
{
pair<ll, ll>j = query(root, 1, yb, r, r + l - 1);
if (j.first!=j.second)
{
cout << "U";
}
else
{
cout << "S";
update(root, 1, yb, r, r + l - 1, 1);
}
}
}
cout << endl;
}
K. Keep Fighting
思路:特判掉特殊情况后,先暴力掉所有牌用掉的情况,最后枚举单独去三重循环枚举所有可能即可得出,记得做个最大数限制
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
inline ll read()
{
register ll x = 0, f = 1;
char c = getchar();
while (c < '0' || c>'9')
{
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
c = getchar();
}
return x * f;
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
struct ss
{
ll l, r;
friend bool operator<(const ss& a, const ss& b)
{
return a.l < b.l;
}
};
int main()
{
fio();
ll n,p,k;
cin>>n>>p>>k;
ll cnt=0;
vector<ll>k1,k2;
for(ll i=1;i<=n;i++)
{
char f;
ll x;
cin>>f;
if(f=='!')cnt++;
else
{
cin>>x;
if(f=='*'&&x==1)continue;
if(f=='*')k1.push_back(x);
else k2.push_back(x);
}
}
sort(k1.begin(),k1.end(),greater<>());//mul
sort(k2.begin(),k2.end(),greater<>());//add
//ll ans=0;
if(cnt==0||(p==0&&k2.size()==0))
{
cout<<"*"<<endl;
return 0;
}
else if(p&&(k1.size()==0&&k2.size()==0))
{
ll f=k/p+(k%p>0);//cnt个数
ll zq=f/cnt;
if(f%cnt==0)zq--;
zq=max(zq,(ll)0);
cout<<f+(zq)*(n-cnt)<<endl;
return 0;
}
ll ad=0;
for(auto x:k2){
ad+=x;
}
function<bool(ll)>ck=[&](ll x)
{
if(x>=k)
{
return 1;
}
else return 0;
};
ll ans=0;//轮
ll att=p;
while(1)
{
ll cm=p;//attack
ll f=att+ad;//res
f=min(1000000001ll,f);
ll pd=0;
if(ck(f*cnt)){
pd=1;
}
for(auto j:k1){
if(ck(f*cnt)){
pd=1;
break;
}else{
f=min(1000000001ll,f);
f*=j;
f=min(1000000001ll,f);
}
}
if(ck(f*cnt)){
pd=1;
}
if(pd){
break;
}else{
att=f;
ans+=n;
k-=att*cnt;
}
}
att=min(1000000001ll,att);
ll op=n;
for(ll l=1;l<=cnt;l++){
ll f=1;
for(ll i=0;i<=k1.size();i++){
ll sum=0;
if(i!=0)
{
f=min(1000000001ll,f);
f*=k1[i-1];
f=min(1000000001ll,f);
}
for(ll j=0;j<=k2.size();j++){
if(i+l+j>=op)continue;
if(j!=0){
sum+=k2[j-1];
sum=min(sum,1000000001ll);
}
if(i+j+l<op){
if(ck(min((att+sum)*f,1000000001ll)*l)){
op=min(op,i+j+l);
}
}
}
}
}
ans+=op;
cout<<ans<<"\n";
}
L. LED Counter
思路:对于每个字符串枚举0到9即可.0到9的字符串第一个样例有给出
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
inline ll read()
{
register ll x = 0, f = 1;
char c = getchar();
while (c < '0' || c>'9')
{
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
c = getchar();
}
return x * f;
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
struct ss
{
ll l, r;
friend bool operator<(const ss& a, const ss& b)
{
return a.l < b.l;
}
};
string e[20] = { "GGGgGGG","gggggGG","gGGGGGg","ggGGGGG","GggGgGG","GgGGGgG","GGGGGgG","ggGggGG","GGGGGGG","GgGGGGG" };
int main()
{
fio();
ll n;
cin >> n;
//cout<<e[1]<<endl;
while (n--)
{
string f;
cin >> f;
ll cnt = 0;
ll ok = 0;
for (ll j = 0; j <= 9; j++)
{
ll pd = 0;
for (ll i = 0; i < f.size(); i++)
{
if (e[j][i] == f[i])continue;
else if (f[i] == 'g' || f[i] == 'G')
{
pd = 2;
break;
}
else if (f[i] == '+' || f[i] == '-')
{
pd = 1;
}
}
if (pd == 0||pd==1)cnt = j;
if (pd == 1)ok++;
}
if (ok >= 2)
cout << "*";
else cout << cnt;
}
cout << endl;
return 0;
}