zoukankan      html  css  js  c++  java
  • 2015 Multi-University Training Contest 1(7/12)

    2015 Multi-University Training Contest 1

    A.OO’s Sequence

    计算每个数的贡献
    找出第(i)个数左边最靠右的因子位置(lp)和右边最靠左的因子位置(rp)
    对答案的贡献就是((rp-i)*(i-lp))
    最后答案就是(sum_{i=1}^{n}(rp_i-i)*(i-lp_i))
    预处理出来所有的因子,复杂度(O(nsqrt{10000}))

    //#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 long long int LL;
    const int MAXN = 1e5+7;
    const LL MOD = 1e9+7;
    int n,A[MAXN],pos[MAXN],rp[MAXN],lp[MAXN];
    vector<int> vec[MAXN];
    void preprocess(){
        for(int i = 1; i <= 10000; i++){
            for(int j = i; j <= 10000; j += i){
                vec[j].push_back(i);
            }
        }
    }
    void solve(){
        for(int i = 1; i <= n; i++) scanf("%d",&A[i]);
        memset(pos,0,sizeof(pos));
        for(int i = 1; i <= n; i++){
            lp[i] = 0;
            for(int x : vec[A[i]]) lp[i] = max(lp[i],pos[x]);
            pos[A[i]] = i;
        }
        memset(pos,0x3f,sizeof(pos));
        for(int i = n; i >= 1; i--){
            rp[i] = n + 1;
            for(int x : vec[A[i]]) rp[i] = min(rp[i],pos[x]);
            pos[A[i]] = i;
        }
        LL ret = 0;
        for(int i = 1; i <= n; i++) ret = (ret + (i-lp[i]) * (rp[i]-i)) % MOD;
        printf("%I64d
    ",ret);
    }
    int main(){
        preprocess();
        while(scanf("%d",&n)!=EOF) solve();    
        return 0;
    }
    

    B.Assignment

    把每个位置作为右端点固定之后找长度最长的可行序列
    ST表配合二分来找
    复杂度(O(nlog n))

    //#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;
    typedef long long int LL;
    int n,k,ST[2][MAXN][20];
    int qmin(int L, int R){
        int d = log2(R-L+1);
        return min(ST[0][L][d],ST[0][R-(1<<d)+1][d]);
    }
    int qmax(int L, int R){
        int d = log2(R-L+1);
        return max(ST[1][L][d],ST[1][R-(1<<d)+1][d]);
    }
    void solve(){
        scanf("%d %d",&n,&k);
        for(int i = 1; i <= n; i++){
            scanf("%d",&ST[0][i][0]);
            ST[1][i][0] = ST[0][i][0];
        }
        for(int j = 1; (1<<j) <= n; j++){
            for(int i = 1; i + (1<<j) - 1 <= n; i++){
                ST[0][i][j] = min(ST[0][i][j-1],ST[0][i+(1<<(j-1))][j-1]);
                ST[1][i][j] = max(ST[1][i][j-1],ST[1][i+(1<<(j-1))][j-1]);
            }
        }
        LL ret = 0;
        for(int i = 1; i <= n; i++){
            int l = 1, r = i;
            while(l<=r){
                int mid = (l+r) >> 1;
                if(qmax(mid,i)<qmin(mid,i)+k) r = mid - 1;
                else l = mid + 1;
            }
            ret += i - l + 1;
        }
        printf("%I64d
    ",ret);
    }
    int main(){
        int T;
        for(scanf("%d",&T); T; T--) solve();
        return 0;
    }
    

    C.Bombing plan

    树形DP
    难点在于当前点的选择会影响祖先节点的其他子树
    可以先不考虑祖先节点的其他子树,只考虑它还能向上延申最远距离
    (f[i][j])表示节点(i)能再向上至少控制(j)个节点的最小消耗

    //#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;
    const int MAXM = 2e2+7;
    const int D = 1e2;
    const int INF = 0x3f3f3f3f;
    typedef long long int LL;
    int n,dist[MAXN],f[MAXN][MAXM],depth[MAXN],sum[MAXN][MAXM];
    vector<int> G[MAXN];
    int dfs(int u, int par){
        depth[u] = depth[par] + 1;
        int maxd = depth[u];
        memset(sum[u],0,sizeof(sum[u]));
        fill(begin(f[u]),end(f[u]),n);
        for(int v : G[u]) if(v!=par){
            maxd = max(maxd,dfs(v,u));
            for(int i = -100; i <= 100; i++) sum[u][i+D] += f[v][i+D];
        }
        for(int i = -100; i < 0; i++) f[u][i+D] = min(f[u][i+D],sum[u][i+D+1]);
        for(int i = 0; i <= 100; i++){
            for(int v : G[u]){
                if(v==par) continue;
                f[u][D+i] = min(f[u][D+i],f[v][D+i+1]+sum[u][D-i]-f[v][D-i]);
            }
        }
        for(int i = -100; i <= depth[u] - maxd - 1; i++) f[u][i+D] = 0;
        f[u][dist[u]+D] = min(f[u][dist[u]+D],1+sum[u][D-dist[u]]);
        for(int i = 99; i >= -100; i--) f[u][i+D] = min(f[u][i+D],f[u][i+1+D]);
        return maxd;
    }
    void solve(){
        for(int i = 1; i <= n; i++) scanf("%d",&dist[i]);
        for(int i = 1; i <= n; i++) G[i].clear();
        for(int i = 1; i < n; i++){
            int u, v;
            scanf("%d %d",&u,&v);
            G[u].push_back(v); G[v].push_back(u);
        }
        dfs(1,0);
        printf("%d
    ",f[1][D]);
    }
    int main(){
        while(scanf("%d",&n)!=EOF) solve();    
        return 0;
    }
    

    D.Candy Distribution

    E.Pocket Cube

    F.Tree chain problem

    评测机出问题了 测不了不知道对不对
    按链的LCA深度排序
    然后DP

    //#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,dfn[MAXN],son[MAXN],sz[MAXN],tp[MAXN],depth[MAXN],par[MAXN][20],num,sum[MAXN],f[MAXN];
    vector<pair<pair<int,int>,int> > chain[MAXN];
    vector<int> G[MAXN];
    void dfs1(int u, int fa){
        sz[u] = 1; son[u] = 0;
        depth[u] = depth[par[u][0] = fa] + 1;
        for(int i = 1; par[u][i-1]; i++) par[u][i] = par[par[u][i-1]][i-1];
        for(int v : G[u]){
            if(v==fa) continue;
            dfs1(v,u);
            sz[u] += sz[v];
            if(sz[son[u]]<sz[v]) son[u] = v;
        }
    }
    void dfs2(int u, int top){
        tp[u] = top;
        dfn[u] = ++num;
        if(son[u]) dfs2(son[u],top);
        for(int v : G[u]){
            if(v==son[u] or v==par[u][0]) continue;
            dfs2(v,v);
        }
    }
    int LCA(int u, int v){
        while(tp[u]!=tp[v]){
            if(depth[tp[u]]<depth[tp[v]]) swap(u,v);
            u = par[tp[u]][0];
        }
        if(depth[u]<depth[v]) return u;
        else return v;
    }
    void dfs(int u){
        sum[u] = 0;
        for(int v : G[u]){
            if(v==par[u][0]) continue;
            dfs(v);
            sum[u] += f[v];
        }
        f[u] = sum[u];
        for(auto ch : chain[u]){
            int x = ch.first.first, y = ch.first.second, w = ch.second;
            int maxx = sum[u] + w;
            if(x!=u){
                if(sz[x]!=1) maxx += sum[x];
                int z = x;
                for(int i = 0; depth[z]-depth[u]-1; i++) if((depth[z]-depth[u]-1)&(1<<i)) z = par[z][i];
                if(sz[z]!=1) maxx -= f[z];
            }
            if(y!=u){
                if(sz[y]!=1) maxx += sum[y];
                int z = y;
                for(int i = 0; depth[z]-depth[u]-1; i++) if((depth[z]-depth[u]-1)&(1<<i)) z = par[z][i];
                if(sz[z]!=1) maxx -= f[z];
            }
            f[u] = max(f[u],maxx);
        }
    }
    void solve(){
        scanf("%d %d",&n,&m);
        for(int i = 1; i <= n; i++) G[i].clear();
        for(int i = 1; i <= n; i++) chain[i].clear();
        num = 0;
        for(int i = 1; i < n; i++){
            int u, v; scanf("%d %d",&u,&v);
            G[u].push_back(v); G[v].push_back(u);
        }
        dfs1(1,0); dfs2(1,1);
        for(int i = 0; i < m; i++){
            int u, v, w;
            scanf("%d %d %d",&u,&v,&w);
            chain[LCA(u,v)].push_back(make_pair(make_pair(u,v),w));
        }
        dfs(1);
        printf("%d
    ",*max_element(f+1,f+1+n));
    }
    int main(){
        int T;
        for(scanf("%d",&T); T; T--) solve();
        return 0;
    }
    

    G. Tricks Device

    保留最短路上的边
    然后对于第一问跑最小割
    第二问删去最短的一条路径即可

    //#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 = 2222;
    const int INF = 0x3f3f3f3f;
    #define S 1
    #define T n
    struct EDGE{
        int to,cap,rev;
        EDGE(){};
        EDGE(int to, int cap, int rev):to(to),cap(cap),rev(rev){};
    };
    vector<EDGE> G[MAXN];
    int n,m,iter[MAXN],rk[MAXN];
    void ADDEDGE(int u, int v, int cap){
        G[u].push_back(EDGE(v,cap,(int)G[v].size()));
        G[v].push_back(EDGE(u,0,(int)G[u].size()-1));
    }
    bool bfs(){
        memset(rk,0,sizeof(rk));
        memset(iter,0,sizeof(iter));
        rk[S] = 1;
        queue<int> que;
        que.push(S);
        while(!que.empty()){
            int u = que.front();
            que.pop();
            for(auto e : G[u]){
                if(!e.cap or rk[e.to]) continue;
                rk[e.to] = rk[u] + 1;
                que.push(e.to);
            }
        }
        return rk[T]!=0;
    }
    int dfs(int u, int flow){
        if(u==T) return flow;
        for(int &i = iter[u]; i < (int)G[u].size(); i++){
            auto &e = G[u][i];
            if(!e.cap or rk[e.to]!=rk[u]+1) continue;
            int d = dfs(e.to,min(e.cap,flow));
            if(d){
                e.cap -= d;
                G[e.to][e.rev].cap += d;
                return d;
            }
        }
        return 0;
    }
    int Dinic(){
        int flow = 0;
        while(bfs()){
            int d = dfs(S,INF);
            while(d){
                flow += d;
                d = dfs(S,INF);
            }
        }
        return flow;
    }
    int dist[MAXN];
    vector<pair<int,int> > GG[MAXN];
    void Dijkstra(){
        memset(dist,0x3f,sizeof(dist));
        dist[1] = 0;
        priority_queue<pair<int,int>, vector<pair<int,int>>,greater<pair<int,int>>> que;
        que.push(make_pair(dist[1],1));
        while(!que.empty()){
            auto p = que.top();
            que.pop();
            if(dist[p.second]!=p.first) continue;
            int u = p.second;
            for(auto &e : GG[u]){
                int v = e.first, w = e.second;
                if(dist[v]<=dist[u]+w) continue;
                dist[v] = dist[u] + w;
                que.push(make_pair(dist[v],v));
            }
        }
        for(int i = 1; i <= n; i++){
            for(auto &e : GG[i]){
                int v = e.first, w = e.second;
                if(dist[i]+w==dist[v]){
                    ADDEDGE(i,v,1);
                }
            }
        }
    }
    int BFS(){
        memset(dist,INF,sizeof(dist));
        dist[S] = 0;
        queue<int> que;
        que.push(S);
        while(!que.empty()){
            int u = que.front();
            que.pop();
            for(auto e : G[u]){
                int v = e.to;
                if(dist[v]!=INF) continue;
                dist[v] = dist[u] + 1;
                que.push(v);
            }
        }
        return dist[T]==INF?m:dist[T];
    }
    void solve(){
        for(int i = 1; i <= n; i++) G[i].clear(), GG[i].clear();
        for(int i = 1; i <= m; i++){
            int u, v, w;
            scanf("%d %d %d",&u,&v,&w);
            GG[u].push_back(make_pair(v,w));
            GG[v].push_back(make_pair(u,w));
        }
        Dijkstra();
        cout << Dinic() << ' ' << m - BFS() << endl;
    }
    int main(){
        while(scanf("%d %d",&n,&m)!=EOF) solve();
        return 0;
    }
    

    H. Unstable

    I.Annoying problem

    //#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,q,dfn[MAXN],idx,dist[MAXN],par[MAXN][20],depth[MAXN],ret,rdfn[MAXN];
    vector<pair<int,int> > G[MAXN];
    void dfs(int u, int f){
        dfn[u] = ++idx;
        rdfn[idx] = u;
        depth[u] = depth[par[u][0] = f] + 1;
        for(int i = 1; par[u][i-1]; i++) par[u][i] = par[par[u][i-1]][i-1];
        for(auto &e : G[u]){
            if(e.first==f) continue;
            dist[e.first] = dist[u] + e.second;
            dfs(e.first,u);
        }
    }
    int LCA(int u, int v){
        if(depth[u]<depth[v]) swap(u,v);
        for(int i = 0; depth[u] - depth[v]; 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];
    }
    set<int> S1,S2;
    int cal(int u){
        int x,y;
        if(S1.lower_bound(dfn[u]+1)!=S1.end() and S2.lower_bound(-dfn[u]+1)!=S2.end()){
            x = -*S2.lower_bound(-dfn[u]+1);
            y = *S1.lower_bound(dfn[u]+1);
        }
        else{
            x = *S1.begin();
            y = *S1.rbegin();
        }
        x = rdfn[x]; y = rdfn[y];
        return dist[u] + dist[LCA(x,y)] - dist[LCA(x,u)] - dist[LCA(y,u)];
    }
    void rua(){
        int op, x;
        scanf("%d %d",&op,&x);
        if(op==1){
            if(!S1.count(dfn[x])){
                if(!S1.empty()) ret += cal(x);
                S1.insert(dfn[x]);
                S2.insert(-dfn[x]);
            }
        }
        else{
            if(S1.count(dfn[x])){
                S1.erase(dfn[x]);
                S2.erase(-dfn[x]);
                if(!S1.empty()) ret -= cal(x);
            }
        }
        printf("%d
    ",ret);
    }
    void solve(int kase){
        scanf("%d %d",&n,&q);
        for(int i = 1; i <= n; i++) G[i].clear();
        memset(par,0,sizeof(par));
        idx = 0; S1.clear(); S2.clear(); ret = 0;
        for(int i = 1; i < n; i++){
            int u, v, w;
            scanf("%d %d %d",&u,&v,&w);
            G[u].push_back(make_pair(v,w));
            G[v].push_back(make_pair(u,w));
        }
        dfs(1,0);
        printf("Case #%d:
    ",kase);
        while(q--) rua();
    }
    int main(){
        int T, kase = 0;
        for(scanf("%d",&T); T; T--) solve(++kase);
        return 0;
    }
    

    J. Y sequence

    容斥+迭代
    迭代枚举答案(m),然后计算删掉的个数,对于每个指数(pw)计算一遍,删掉的数量是(pow(m,frac{1}{pw})),发现是个关于因子的容斥,所以容斥系数是莫比乌斯函数
    二分会T,所以用迭代来做,复杂度很玄学

    //#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 long long int LL;
    const int MAXN = 111;
    int npm[MAXN],mu[MAXN];
    LL n,r;
    vector<int> prime;
    void sieve(){
        mu[1] = 1;
        for(int i = 2; i < MAXN; i++){
            if(!npm[i]){
                prime.push_back(i);
                mu[i] = -1;
            }
            for(int j = 0; j < (int)prime.size(); j++){
                if(i*prime[j]>=MAXN) break;
                npm[i*prime[j]] = true;
                mu[i*prime[j]] = -mu[i];
                if(i%prime[j]==0){
                    mu[i*prime[j]] = 0;
                    break;
                }
            }
        }
    }
    vector<int> pw;
    void prep(){
        pw.clear();
        for(int i = 0; prime[i]<=r; i++){
            int sz = pw.size();
            for(int j = 0; j < sz; j++){
                int np = pw[j] * prime[i];
                if(np>63) continue;
                pw.push_back(np);
            }
            pw.push_back(prime[i]);
        }
    }
    LL f(LL m){
        LL tot = 0;
        for(auto p : pw) tot += mu[p] * ((LL)pow(m+.5,1./p) - 1);
        return m-1+tot;
    }
    void solve(){
        scanf("%I64d %I64d",&n,&r);
        prep();
        LL tmp = f(n), ret = n;
        while(tmp<n){
            ret += n - tmp;
            tmp = f(ret);
        }
        printf("%I64d
    ",ret);
    }
    
    int main(){
        sieve();
        int T;
        for(scanf("%d",&T); T; T--) solve();
        return 0;
    }
    

    K. Solid Geometry Homework

    L. Circles Game

    只会口胡
    圆扫描线+树上删边游戏

  • 相关阅读:
    安卓学习26(ListView的焦点问题)
    ACL Contest1 B- Sum is Multiple 数论,EXGCD
    P4137 Rmq Problem / mex 可持久化线段树求区间MEX
    [可持久化权值线段树] [模板] [数组版本]
    CodeForces383C Propagating tree 思维 线段树 DFS序
    CodeForces 558E A Simple Task 线段树 桶排思想
    P1471 方差 线段树维护区间方差
    Leetcode1521 找到最接近目标的函数值 位运算
    CodeForces-739C Alyona and towers 线段树经典套路之维护左中右
    GYM-101194F Mr. Panda and Fantastic Beasts 后缀数组套路
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12948997.html
Copyright © 2011-2022 走看看