2017-2018 ACM-ICPC Latin American Regional Programming Contest PART (11/13)

\[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",n);
            else printf("%d\n",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\n",i);
            ok = true;
            break;
        }
        del(i);
        if(cnt[i]){
            del(i);
            if((mp.size()==1&&tot==k)||mp.empty()){
                printf("-%d\n",i);
                ok = true;
                break;
            }
            for(int j = 1; j <= k; j++){
                add(j);
                if((mp.size()==1&&tot==k)||mp.empty()){
                    printf("-%d +%d\n",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\n",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\n",solve());
    return 0;
}

\(G.Gates\ of\ uncertainty\)

比较简单的树形DP,每个节点\(2\times 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\n",(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\n",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\n",tot+edge.at(make_pair(u,v))-getmaxdist(u,v));
    }
    return 0;
}

\(J.Jumping\ frog\)

考虑各个\(k\),对于\(gcd(n,k)\)相同的一类,如果其中一种是是可行的,则其他都可行,都跳相同的那部分石头,所以问题转化为对于所有\(n\)的因子,判断是否存在可行解,\(O(n\sqrt{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\n",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进制的最小数,后缀数组处理出各个位置的排名,然后用堆搞

扫描二维码关注公众号,回复: 8763203 查看本文章
//#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\n",res);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/kikokiko/p/12213645.html