• 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;
    }
    
  • 相关阅读:
    C语言宏中"#"和"##"的用法
    Ubuntu 14.04 LTS 安装和配置Bochs
    C和C++中static的比较
    总线设备驱动模型
    驱动设计的思想:面向对象/分层/分离
    基于分层思想的驱动程序软件框架
    单元测试指南
    Apollo移植
    剑指offer python版 数组中出现次数超过一半的数字
    剑指offer python版 字符串的排列
  • 原文地址:https://www.cnblogs.com/kikokiko/p/13527893.html
Copyright © 2020-2023  润新知