$$2017-2018 ACM-ICPC Latin American Regional Programming Contest$$
(A.Arranging tiles)
(B.Buggy ICPC)
分元音位置情况和数量讨论,没有元音答案是1,如果有元音但不在第一个位置上是无法构造出来的,然后其他情况找到最初始的情况的辅音数量即可
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+7;
char s[MAXN];
const char vowel[5] = {'a','e','i','o','u'};
int n;
vector<int> vowel_pos;
int main(){
scanf("%s",s);
n = strlen(s);
for(int i = 0; i < n; i++){
for(int j = 0; j < 5; j++){
if(s[i]==vowel[j]){
vowel_pos.emplace_back(i);
break;
}
}
}
if(vowel_pos.empty()) puts("1");
else{
if(vowel_pos[0]!=0) puts("0");
else{
if(vowel_pos.size()==1) printf("%d
",n);
else printf("%d
",vowel_pos[(vowel_pos.size()+1)>>1]-vowel_pos[((vowel_pos.size()+1)>>1)-1]);
}
}
return 0;
}
(C.Complete Naebbirac's sequence)
签到 暴力判断
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e4+7;
int k,n,A[MAXN],cnt[MAXN],tot;
map<int,int> mp;
void del(int x){
mp[cnt[x]]--;
if(mp[cnt[x]]==0) mp.erase(cnt[x]);
cnt[x]--;
if(!cnt[x]) tot--;
if(cnt[x]) mp[cnt[x]]++;
}
void add(int x){
if(cnt[x]){
mp[cnt[x]]--;
if(mp[cnt[x]]==0) mp.erase(cnt[x]);
}
if(!cnt[x]) tot++;
cnt[x]++;
mp[cnt[x]]++;
}
int main(){
scanf("%d %d",&k,&n);
for(int i = 1; i <= n; i++){
scanf("%d",&A[i]);
cnt[A[i]]++;
}
for(int i = 1; i <= k; i++){
if(!cnt[i]) continue;
mp[cnt[i]]++;
tot++;
}
bool ok = false;
for(int i = 1; i <= k&&!ok; i++){
add(i);
if((mp.size()==1&&tot==k)||mp.empty()){
printf("+%d
",i);
ok = true;
break;
}
del(i);
if(cnt[i]){
del(i);
if((mp.size()==1&&tot==k)||mp.empty()){
printf("-%d
",i);
ok = true;
break;
}
for(int j = 1; j <= k; j++){
add(j);
if((mp.size()==1&&tot==k)||mp.empty()){
printf("-%d +%d
",i,j);
ok = true;
break;
}
del(j);
}
add(i);
}
}
if(!ok) puts("*");
return 0;
}
(D.Daunting device)
暂时无法用线段树解决,要是能多给0.5秒应该就可以了,最后用分块过了,用map直接超时了,只能自己实现一个容器
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef int_fast64_t LL;
const int MAXN = 1e5+7;
int n,m,q,sz,blk,l[MAXN],r[MAXN],belong[MAXN],lazy[MAXN],A[MAXN],cnt[MAXN];
struct STA{
int arr[MAXN>>1],stk[MAXN],top;
int& operator [] (int idx){ return arr[idx]; }
void clear(){ while(top) arr[stk[top--]] = 0; }
void dec(int pos, int x){ arr[pos] -= x; }
void inc(int pos, int x){
if(!arr[pos]) stk[++top] = pos;
arr[pos]+=x;
}
}sta[400];
void pushdown(int p){
if(!lazy[p]) return;
for(int i = l[p]; i <= r[p]; i++) A[i] = lazy[p];
lazy[p] = 0;
}
void cover(int L, int R, int x){
int bl = belong[L], br = belong[R];
if(bl==br){
pushdown(bl);
for(int i = L; i <= R; i++){
sta[bl].dec(A[i],1);
A[i]=x;
}
sta[bl].inc(x,R-L+1);
}
else{
pushdown(bl);
pushdown(br);
for(int i = L; i <= r[bl]; i++){
sta[bl].dec(A[i],1);
A[i]=x;
}
sta[bl].inc(x,r[bl]-L+1);
for(int i = l[br]; i <= R; i++){
sta[br].dec(A[i],1);
A[i]=x;
}
sta[br].inc(x,R-l[br]+1);
for(int i = bl+1; i <= br-1; i++){
lazy[i] = x;
sta[i].clear();
sta[i].inc(x,r[i]-l[i]+1);
}
}
}
int main(){
scanf("%d %d %d",&n,&m,&q);
sz = pow(n,0.5);
blk = n/sz+(n%sz!=0?1:0);
for(int i = 1; i <= n; i++) belong[i] = (i-1)/sz+1;
for(int i = 1; i <= blk; i++){
l[i] = sz*(i-1)+1;
r[i] = sz*i;
sta[i].inc(1,r[i]-l[i]+1);
}
r[blk] = n;
sta[blk][1] = r[blk]-l[blk]+1;
for(int i = 1; i <= n; i++) A[i] = 1;
for(int i = 1; i <= q; i++){
int p,x,a,b;
scanf("%d %d %d %d",&p,&x,&a,&b);
LL s = 0;
for(int j = 1; j <= blk; j++) s+=sta[j][p];
int L = (a+s*s)%n, R = (a+(s+b)*(s+b))%n;
if(L>R) swap(L,R);
cover(L+1,R+1,x);
}
for(int i = 1; i <= blk; i++) for(int j = 1; j <= m; j++) cnt[j] += sta[i][j];
int maxx = 0;
for(int i = 1; i <= m; i++) maxx = maxx > cnt[i] ? maxx : cnt[i];
printf("%d
",maxx);
return 0;
}
(E.Enigma)
数位DP,(f[i][d][k])表示当前处理到第(i)位,当前选(d),余数为(k)的情况下上一位能选的最小的值,从低位往高位转移
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e3+7;
char s[MAXN];
int n,m,f[MAXN][10][MAXN],mod[MAXN];
int main(){
scanf("%s %d",s+1,&n);
m = strlen(s+1);
s[m+1] = '0';
memset(f,255,sizeof(f));
mod[m] = 1;
for(int i = 0; i <= 9; i++) f[m+1][i][0] = 0;
for(int i = m-1; i >= 1; i--) mod[i] = mod[i+1]*10%n;
for(int i = m; i >= 1; i--){
for(int d = (s[i]=='?'?0:s[i]-'0'); d <= (s[i]=='?'?9:s[i]-'0'); d++){
int num = d*mod[i]%n;
for(int j = n-1; j >= 0; j--){
for(int k = 9; k >= 0; k--){
f[i][d][j] = f[i+1][k][j>=num?j-num:j+n-num]==-1?f[i][d][j]:k;
}
}
}
}
vector<int> vec;
for(int i = 1; i <= 9; i++) if(f[1][i][0]!=-1){
vec.emplace_back(i);
break;
}
if(vec.empty()) puts("*");
else{
int md = 0;
for(int i = 2; i <= m; i++){
int p = vec.back()*mod[i-1]%n;
vec.emplace_back(f[i-1][vec.back()][md]);
md = md>=p?md-p:md-p+n;
}
for(int x : vec) printf("%d",x); puts("");
}
return 0;
}
(F.Fundraising)
第二维离散化之后排序先去重,按第一维从大到小DP,线段树维护
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+7;
using LL = int_fast64_t;
int n,m;
pair<pair<int,int>,LL> sta[MAXN];
struct SegmentTree{
LL maxx[MAXN<<2];
int l[MAXN<<2],r[MAXN<<2];
#define ls(rt) (rt) << 1
#define rs(rt) (rt) << 1 | 1
void pushup(int rt){ maxx[rt] = max(maxx[ls(rt)],maxx[rs(rt)]); }
void build(int L, int R, int rt){
l[rt] = L; r[rt] = R;
maxx[rt] = 0;
if(L+1==R) return;
int mid = (L+R) >> 1;
build(L,mid,ls(rt)); build(mid,R,rs(rt));
}
void update(int pos, int rt, LL x){
if(l[rt]+1==r[rt]){
maxx[rt] = x;
return;
}
int mid = (l[rt]+r[rt]) >> 1;
if(pos<mid) update(pos,ls(rt),x);
else update(pos,rs(rt),x);
pushup(rt);
}
LL query(int L, int R, int rt){
if(l[rt]>=R || L>=r[rt]) return 0;
if(L<=l[rt] && r[rt]<=R) return maxx[rt];
return max(query(L,R,ls(rt)),query(L,R,rs(rt)));
}
}ST;
LL solve(){
ST.build(1,m+1,1);
LL res = 0;
vector<pair<int,LL>> vec;
for(int i = n; i >= 1; i--){
if(sta[i].first.first!=sta[i+1].first.first){
for(auto p : vec){
if(ST.query(p.first,p.first+1,1)>=p.second) continue;
ST.update(p.first,1,p.second);
}
vec.clear();
}
LL maxx = ST.query(sta[i].first.second+1,m+1,1) + sta[i].second;
res = max(res,maxx);
vec.emplace_back(make_pair(sta[i].first.second,maxx));
}
return res;
}
int main(){
scanf("%d",&n);
vector<int> vec;
for(int i = 1; i <= n; i++){
scanf("%d %d %I64d",&sta[i].first.first,&sta[i].first.second,&sta[i].second);
vec.emplace_back(sta[i].first.second);
}
sort(sta+1,sta+1+n);
sort(vec.begin(),vec.end());
int nn = 1, r = 2;
while(r<=n){
if(sta[nn].first==sta[r].first) sta[nn].second+=sta[r].second;
else sta[++nn] = sta[r];
r++;
}
n = nn;
m = vec.size();
for(int i = 1; i <= n; i++) sta[i].first.second = lower_bound(vec.begin(),vec.end(),sta[i].first.second) - vec.begin() + 1;
printf("%I64d
",solve());
return 0;
}
(G.Gates of uncertainty)
比较简单的树形DP,每个节点(2 imes 2)个状态
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef int_fast64_t LL;
const LL MOD = 1e9+7;
const int MAXN = 2e5+7;
pair<int,int> son[MAXN];
int n,tag[MAXN];
LL f[MAXN][2][2];
void solve(int u){
if(u==0) return;
int sa = son[u].first;
int sb = son[u].second;
solve(sa);
solve(sb);
for(int i1 = 0; i1 <= 1; i1++)
for(int j1 = 0; j1 <= 1; j1++)
for(int i2 = 0; i2 <= 1; i2++)
for(int j2 = 0; j2 <= 1; j2++)
f[u][!(i1&&i2)][tag[u]!=-1?tag[u]:!(j1&&j2)] = (f[u][!(i1&&i2)][tag[u]!=-1?tag[u]:!(j1&&j2)]+f[sa][i1][j1]*f[sb][i2][j2]%MOD)%MOD;
}
int main(){
scanf("%d",&n);
for(int i = 1; i <= n; i++) scanf("%d %d %d",&son[i].first,&son[i].second,&tag[i]);
f[0][0][0] = f[0][1][1] = 1; f[0][1][0] = f[0][0][1] = 0;
solve(1);
printf("%I64d
",(f[1][0][1]+f[1][1][0])%MOD);
return 0;
}
(H.Hard choice)
签到
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
int main(){
int A[10];
for(int i = 1; i <= 6; i++) scanf("%d",&A[i]);
printf("%d
",max(0,A[4]-A[1])+max(0,A[5]-A[2])+max(0,A[6]-A[3]));
return 0;
}
(I.Imperial roads)
最小生成树,树上倍增+LCA维护最小生成树路径上最大边,替换即可
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+7;
int n,m,q,depth[MAXN],par[MAXN][20],maxdist[MAXN][20],root[MAXN],tot;
map<pair<int,int>,int> edge;
vector<pair<int,pair<int,int>>> vec;
vector<pair<int,int>> G[MAXN];
int findroot(int u){
if(u!=root[u]) root[u] = findroot(root[u]);
return root[u];
}
int LCA(int u, int v){
if(depth[u]<depth[v]) swap(u,v);
for(int i = 0; i < 20; i++) if((depth[u]-depth[v])&(1<<i)) u = par[u][i];
if(u==v) return u;
for(int i = 19; i >= 0; i--) if(par[u][i]!=par[v][i]){
u = par[u][i];
v = par[v][i];
}
return par[u][0];
}
int getmaxdist(int u, int v){
int maxx = 0;
int lca = LCA(u,v);
int dep = depth[lca] + 1;
for(int i = 0; dep<depth[u]; i++) if((dep-depth[u])&(1<<i)){
maxx = max(maxx,maxdist[u][i]);
u = par[u][i];
}
for(int i = 0; dep<depth[v]; i++) if((dep-depth[v])&(1<<i)){
maxx = max(maxx,maxdist[v][i]);
v = par[v][i];
}
if(dep==depth[u]) maxx = max(maxx,maxdist[u][0]);
if(dep==depth[v]) maxx = max(maxx,maxdist[v][0]);
return maxx;
}
void dfs(int u, int f){
depth[u] = depth[f] + 1;
for(int i = 1; par[u][i-1]; i++){
par[u][i] = par[par[u][i-1]][i-1];
maxdist[u][i] = max(maxdist[u][i-1],maxdist[par[u][i-1]][i-1]);
}
for(auto e : G[u]){
int v = e.first;
if(v==f) continue;
par[v][0] = u;
maxdist[v][0] = e.second;
dfs(v,u);
}
}
int main(){
scanf("%d %d",&n,&m);
vec.resize(m);
for(int i = 0; i < m; i++){
scanf("%d %d %d",&vec[i].second.first,&vec[i].second.second,&vec[i].first);
if(vec[i].second.first>vec[i].second.second) swap(vec[i].second.first,vec[i].second.second);
edge.insert(make_pair(vec[i].second,vec[i].first));
}
sort(vec.begin(),vec.end());
for(int i = 1; i <= n; i++) root[i] = i;
for(int i = 0; i < m; i++){
int u = vec[i].second.first;
int v = vec[i].second.second;
if(findroot(u)==findroot(v)) continue;
G[u].emplace_back(make_pair(v,vec[i].first));
G[v].emplace_back(make_pair(u,vec[i].first));
root[findroot(u)] = findroot(v);
tot += vec[i].first;
}
dfs(1,0);
scanf("%d",&q);
for(int i = 1; i <= q; i++){
int u, v;
scanf("%d %d",&u,&v);
if(u>v) swap(u,v);
printf("%d
",tot+edge.at(make_pair(u,v))-getmaxdist(u,v));
}
return 0;
}
(J.Jumping frog)
考虑各个(k),对于(gcd(n,k))相同的一类,如果其中一种是是可行的,则其他都可行,都跳相同的那部分石头,所以问题转化为对于所有(n)的因子,判断是否存在可行解,(O(nsqrt{n}))
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+7;
char s[MAXN];
int n;
vector<int> factor;
bool ok[MAXN],vis[MAXN];
bool judge(int pos, int m){
vis[pos] = true;
for(int i = (pos+m)%n; ; i = (i+m)%n){
if(s[i]=='P') return false;
if(i==pos) return true;
vis[i] = true;
}
return true;
}
bool check(int m){
memset(vis,0,sizeof(vis));
for(int i = 0; i < n; i++){
if(vis[i]||s[i]=='P') continue;
if(judge(i,m)) return true;
}
return false;
}
int main(){
scanf("%s",s);
n = strlen(s);
factor.emplace_back(1);
for(int i = 2; i * i <= n; i++){
if(n%i!=0) continue;
factor.emplace_back(i);
if(i*i!=n) factor.emplace_back(n/i);
}
for(int fac : factor) ok[fac] = check(fac);
int res = 0;
for(int i = 1; i < n; i++) res+=ok[__gcd(i,n)]?1:0;
printf("%d
",res);
return 0;
}
(K.Keep it covered)
发现有圈的cell可以向四周连出一条边,无圈的cell可以向四周连出两条边,拆点建图跑二分图匹配即可
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 22;
const int dir[4][2] = {{-1,0},{0,-1},{1,0},{0,1}};
int n,m,tot,match[2000];
pair<int,int> node[MAXN][MAXN];
char s[MAXN][MAXN];
bool vis[2000];
vector<int> G[2000];
bool dfs(int u){
vis[u] = true;
for(int v : G[u]){
if(match[v]==-1||(!vis[match[v]]&&dfs(match[v]))){
match[v] = u;
return true;
}
}
return false;
}
bool solve(){
memset(match,255,sizeof(match));
for(int i = 1; i <= tot; i++){
memset(vis,false,sizeof(vis));
if(!dfs(i)) return false;
}
return true;
}
int main(){
scanf("%d %d",&n,&m);
for(int i = 1; i <= n; i++) scanf("%s",s[i]+1);
for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++){
if(s[i][j]=='o') node[i][j].first = node[i][j].second = ++tot;
else{
node[i][j].first = ++tot;
node[i][j].second = ++tot;
}
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
for(int d = 0; d < 4; d++){
int nx = i+dir[d][0];
int ny = j+dir[d][1];
if(nx<1||ny<1||nx>n||ny>m) continue;
G[node[i][j].first].emplace_back(node[nx][ny].first);
if(node[nx][ny].second!=node[nx][ny].first) G[node[i][j].first].emplace_back(node[nx][ny].second);
if(node[i][j].second!=node[i][j].first){
G[node[i][j].second].emplace_back(node[nx][ny].first);
if(node[nx][ny].second!=node[nx][ny].first) G[node[i][j].second].emplace_back(node[nx][ny].second);
}
}
}
}
puts(solve()?"Y":"N");
return 0;
}
(L.Linearville)
(M.Marblecoin)
多个栈合并出365进制的最小数,后缀数组处理出各个位置的排名,然后用堆搞
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 5e5+7;
using LL = int_fast64_t;
const LL MOD = 1e9+7;
int n;
LL spow[MAXN],res;
vector<int> vec[MAXN],ID[MAXN];
int A[MAXN],tot,sa[MAXN],c[MAXN],rk[MAXN],sec[MAXN],all;
void SA(int m){
for(int i = 0; i <= m; i++) c[i] = 0;
for(int i = 1; i <= tot; i++) c[rk[i]=A[i]]++;
for(int i = 1; i <= m; i++) c[i] += c[i-1];
for(int i = 1; i <= tot; i++) sa[c[rk[i]]--] = i;
for(int k = 1; k <= tot; k <<= 1){
int p = 0;
for(int i = tot - k + 1; i <= tot; i++) sec[++p] = i;
for(int i = 1; i <= tot; i++) if(sa[i]>k) sec[++p] = sa[i] - k;
for(int i = 0; i <= m; i++) c[i] = 0;
for(int i = 1; i <= tot; i++) c[rk[sec[i]]]++;
for(int i = 1; i <= m; i++) c[i] += c[i-1];
for(int i = tot; i >= 1; i--) sa[c[rk[sec[i]]]--] = sec[i];
p = 1;
swap(rk,sec);
rk[sa[1]] = 1;
for(int i = 2; i <= tot; i++) rk[sa[i]] = sec[sa[i]]==sec[sa[i-1]]&&sec[sa[i]+k]==sec[sa[i-1]+k] ? p : ++p;
if(p==tot) break;
m = p;
}
}
int main(){
scanf("%d",&n);
spow[0] = 1;
for(int i = 1; i < MAXN; i++) spow[i] = spow[i-1]*365%MOD;
for(int i = 1; i <= n; i++){
int sz;
scanf("%d",&sz);
all += sz;
vec[i].resize(sz);
ID[i].resize(sz);
for(int j = 0; j < sz; j++){
scanf("%d",&vec[i][j]);
ID[i][j] = ++tot;
A[tot] = vec[i][j];
}
A[++tot] = 333;
}
SA(333);
priority_queue<pair<int,pair<int,int>>,vector<pair<int,pair<int,int>>>,greater<pair<int,pair<int,int>>>> que;
for(int i = 1; i <= n; i++) que.push(make_pair(rk[ID[i][0]],make_pair(i,0)));
LL res = 0;
while(all){
auto p = que.top();
que.pop();
res = (res+vec[p.second.first][p.second.second]*spow[all])%MOD;
if(p.second.second<(int)vec[p.second.first].size()-1){
p.first = rk[ID[p.second.first][p.second.second+1]];
p.second.second++;
que.push(p);
}
all--;
}
printf("%I64d
",res);
return 0;
}