Educational Codeforces Round 22

Educational Codeforces Round 22  

A. The Contest

显然先做好所有的然后一并提交

view code
//#pragma GCC optimize("O3")
//#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 = 1111;

void solve(){
    ____();
    int n;  cin >> n;
    vector<int> A(n);
    for(int i = 0; i < n; i++) cin >> A[i];
    int s = accumulate(A.begin(),A.end(),0);
    int m; cin >> m;
    for(int i = 0; i < m; i++){
        int l, r; cin >> l >> r;
        if(s<=r){
            cout << max(s,l) << endl;
            return;
        }
    }
    cout << -1 << endl;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}

B.The Golden Age

点数不会很多,全部找出来,然后在区间里找个最大间隔即可

view code
//#pragma GCC optimize("O3")
//#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 unsigned long long int LL;
LL x, y, l, r;
void solve(){
    cin >> x >> y >> l >> r;
    set<LL> S;
    vector<LL> v1, v2;
    v1.push_back(1);
    LL z = 1;
    while(true){
        if((r+10.) / x > z) z *= x;
        else break;
        v1.push_back(z);
    }
    v2.push_back(1);
    z = 1;
    while(true){
        if((r+10.) / y > z) z *= y;
        else break;
        v2.push_back(z);
    }
    for(auto a : v1) for(auto b : v2) S.insert(a+b);
    LL ret = 0ull;
    vector<LL> A;
    A.push_back(l-1);
    for(auto x : S) if(x>=l and x<=r) A.push_back(x);
    ret = max({ret,r-A.back()});
    for(int i = 1; i < (int) A.size(); i++) ret = max(ret,A[i]-A[i-1]-1);
    cout << ret << endl;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}

C. The Tag Game

显然要走到最远的位置,且在过程中不被抓到,那么只要枚举能走到的最远的位置就好了

view code
//#pragma GCC optimize("O3")
//#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 = 2e5+7;
int n, x, dep[MAXN], par[MAXN], maxd[MAXN];
bool onp[MAXN];
vector<int> G[MAXN];
void dfs(int u, int fa){
    dep[u] = dep[fa] + 1;
    par[u] = fa;
    for(int v : G[u]) if(v!=fa) dfs(v,u);
}
void dfs(int u){
    maxd[u] = dep[u];
    for(int v : G[u]) if(v!=par[u]){
        dfs(v);
        if(!onp[v]) maxd[u] = max(maxd[u],maxd[v]);
    }
}
void solve(){
    ____();
    cin >> n >> x;
    for(int i = 1; i < n; i++){
        int u, v; cin >> u >> v;
        G[u].push_back(v); G[v].push_back(u);
    }
    dfs(1,0);
    int cur = x;
    while(cur) onp[cur] = true, cur = par[cur];
    dfs(1);
    int ret = 0;
    for(int i = 2; i <= n; i++){
        if(!onp[i]) continue;
        if(dep[i]-dep[1]<=dep[x]-dep[i]) continue;
        ret = max(ret,maxd[i]*2-2);
    }
    cout << ret << endl;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}

D. Two Melodies

考虑(dp[i][j])表示第一个序列选到了(i),第二个序列选到了(j)这时候的长度和的最大值

注意不能通过(dp[x][y])转移到(dp[i][j]),也即不能同时转移两个位置,会出现重复覆盖的问题

考虑固定一个进行转移,先枚举第一个序列的位置,然后第二个序列的位置可以从之前的位置转移过来,要求之前的位置满足

  1. 前面没有数
  2. 前面的数和当前数模(7)同余
  3. 前面的数和当前数的差值的绝对值为(1)

我们只要维护模(7)下各个模数的最大值和在各个值得情况下得最大值就能(O(1))转移

网络流也可以做

view code
#pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;
#define VI vector<int>
#define VL vector<LL>
#define pb push_back
#define ALL(V) V.begin(),V.end()
#define sci(x) scanf("%d",&x)
#define scl(x) scanf("%I64d",&x)
#define pii pair<int,int>
#define cmax(a,b) ((a) = (a) > (b) ? (a) : (b))
#define cmin(a,b) ((a) = (a) < (b) ? (a) : (b))
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 5555;
void solve(){
    int n; sci(n);
    VI A(n+1);
    for(int i = 1; i <= n; i++) sci(A[i]);
    vector<VI> f(n+1,VI(n+1));
    VI maxmod(7,0), maxnum(100007,0);
    for(int i = 0; i <= n; i++){
        for(int j = 1; j < i; j++) cmax(maxmod[A[j]%7],f[i][j]), cmax(maxnum[A[j]],f[i][j]);
        for(int j = i + 1; j <= n; j++){
            f[j][i] = f[i][j] = max({f[i][0],maxmod[A[j]%7],maxnum[A[j]-1],maxnum[A[j]+1]}) + 1;
            cmax(maxmod[A[j]%7],f[i][j]); cmax(maxnum[A[j]],f[i][j]);
        }
        fill(ALL(maxmod),0);
        for(int j = 1; j <= n; j++) maxnum[A[j]] = 0;
    }
    int ret = 0;
    for(int i = 0; i <= n; i++) cmax(ret,*max_element(ALL(f[i])));
    cout << ret << endl;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}

E. Army Creation

建一棵主席树,同时记录某个颜色的点出现的次数,如果某个颜色出现的次数大于了(k),就删掉最先出现的那个位置

view code
//#pragma GCC optimize("O3")
//#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 = 2e5+7;
int n, k;
set<int> pos[MAXN];
struct SegmentTree{
    int root[MAXN], ls[MAXN<<5], rs[MAXN<<5], sum[MAXN<<5], tot;
    void modify(int l, int r, int pos, int x, int &rt, int pre){
        rt = ++tot;
        ls[rt] = ls[pre]; rs[rt] = rs[pre]; sum[rt] = sum[pre] + x;
        if(l+1==r) return;
        int mid = (l + r) >> 1;
        if(pos<mid) modify(l,mid,pos,x,ls[rt],ls[pre]);
        else modify(mid,r,pos,x,rs[rt],rs[pre]);
    }
    int query(int l, int r, int L, int R, int rt){
        if(L>=r or l>=R) return 0;
        if(L<=l and r<=R) return sum[rt];
        int mid = (l + r) >> 1;
        return query(l,mid,L,R,ls[rt]) + query(mid,r,L,R,rs[rt]);
    }
}ST;
void solve(){
    ____();
    cin >> n >> k;
    for(int i = 1; i <= n; i++){
        int x; cin >> x;
        int pre = ST.root[i-1];
        if(pos[x].size()==k){
            int rt = 0;
            ST.modify(1,n+1,*pos[x].begin(),-1,rt,pre);
            pre = rt;
            pos[x].erase(pos[x].begin());
        }
        ST.modify(1,n+1,i,1,ST.root[i],pre);
        pos[x].insert(i);
    }
    int q; cin >> q;
    int lastans = 0;
    while(q--){
        int l, r; cin >> l >> r;
        l = (l + lastans) % n + 1;
        r = (r + lastans) % n + 1;
        if(l>r) swap(l,r);
        cout << (lastans = ST.query(1,n+1,l,n+1,ST.root[r])) << endl;
    }
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}

F. Bipartite Checking

每条边有存在的一段时间,考虑线段树分治,由于相邻两个点颜色不能相同,考虑用可撤销扩展域并查集来做,如果两个点(u)(v)连了边,就说明(u)(v)是冲突的,那就(u)(v+n)连边,(u+n)(v)合并,如果(u,v)已经在同一个集合里了说明已经有冲突了

view code
//#pragma GCC optimize("O3")
//#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;
map<pair<int,int>, int> msk;
int f[MAXN<<1], dep[MAXN<<1];
bool bip[MAXN];
inline int findx(int x){ while(x!=f[x]) x = f[x]; return x; }
pair<int,int> merge(int u, int v){
    int fu = findx(u), fv = findx(v);
    if(dep[fu]<dep[fv]) swap(fv,fu);
    auto p = make_pair(fv,dep[fu]);
    f[fv] = fu;
    if(dep[fu]==dep[fv]) dep[fu]++;
    return p;
}
struct SegmentTree{
    int l[MAXN<<2], r[MAXN<<2];
    int head[MAXN<<2], nxt[MAXN<<6], tot;
    pair<int,int> pr[MAXN<<6];
    #define ls(rt) rt << 1
    #define rs(rt) rt << 1 | 1
    void build(int L, int R, int rt = 1){
        l[rt] = L; r[rt] = R;
        head[rt] = -1;
        if(l[rt] + 1 == r[rt]) return;
        int mid = (L + R) >> 1;
        build(L,mid,ls(rt)); build(mid,R,rs(rt));
    }
    void insert(int L, int R, pair<int,int> e, int rt = 1){
        if(L>=r[rt] or l[rt]>=R) return;
        if(L<=l[rt] and r[rt]<=R){
            nxt[tot] = head[rt];
            pr[tot] = e; head[rt] = tot++;
            return;
        }
        insert(L,R,e,ls(rt)); insert(L,R,e,rs(rt));
    }
    void dfs(int rt, bool ok = true){
        stack<pair<int,int> > stk;
        if(ok){
            for(int i = head[rt]; ~i; i = nxt[i]){
                int u = pr[i].first, v = pr[i].second;
                if(findx(u)==findx(v)){
                    ok = false;
                    break;
                }else{
                    assert(findx(u+n)!=findx(v+n));
                    if(findx(u)!=findx(v+n)){
                        stk.push(merge(u,v+n));
                        stk.push(merge(v,u+n));
                    }
                }
            }
        }
        if(l[rt] + 1 == r[rt]) bip[l[rt]] = ok;
        else dfs(ls(rt),ok), dfs(rs(rt),ok);
        while(!stk.empty()){
            auto p = stk.top();
            stk.pop();
            dep[f[p.first]] = p.second; f[p.first] = p.first;
        }
    }
}ST;
void solve(){
    ____();
    cin >> n >> m;
    ST.build(1,m+1);
    for(int i = 1; i <= m; i++){
        int u, v; cin >> u >> v;
        if(u>v) swap(u,v);
        if(msk.count({u,v})) ST.insert(msk[{u,v}],i,{u,v}), msk.erase({u,v});
        else msk.insert({{u,v},i});
    }
    for(auto p : msk) ST.insert(p.second,m+1,p.first);
    for(int i = 1; i <= n * 2; i++) f[i] = i;
    ST.dfs(1);
    for(int i = 1; i <= m; i++) puts(bip[i]?"YES":"NO");
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}
原文地址:https://www.cnblogs.com/kikokiko/p/13527893.html