2019银川网络赛

link

Gym - 102222、2018宁夏邀请赛、2019银川icpc网络预选赛

current: 10 / 13

A. Maximum Element In A Stack

B. Rolling The Polygon

C. Caesar Cipher

D. Take Your Seat

E. 2-3-4 Tree

模拟题

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include 
#include  
#include  
#include   
#include   
#include   
#include    
#include    
#include    
#include    <string>
#include    
#include     
#include     
#include     
#include      
#include       
#include       <set>
#include   
#include 
// #include
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;

template
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

/**********showtime************/
            const int maxn = 5009;
            int tot;
            struct node{
                int cnt;
                int val[3];
                int son[4];
            } tree[maxn *2];

            int newnode() {
                ++tot;
                tree[tot].cnt = 0;
                for(int i=0; i<3; i++) tree[tot].val[i] = 0;
                for(int i=0; i<4; i++) tree[tot].son[i] = 0;
                return tot;
            }

            void insert(int p,  int val) {

                int id = tree[p].cnt;

                for(int i = 0; i < tree[p].cnt; i++) {
                    if(val < tree[p].val[i]) {
                        id = i;
                        break;
                    }
                }
                int flag = 1;
                for(int i=0; i <= tree[p].cnt; i++) if(tree[p].son[i]) flag = 0;
                if(flag) {
                    int cur = tree[p].cnt;
                    while(cur > id) tree[p].val[cur] = tree[p].val[cur-1], cur--;
                    tree[p].val[id] = val;
                    tree[p].cnt++;
                    return;
                }
                if(tree[p].son[id] == 0) tree[p].son[id] = newnode();
                int np =  tree[p].son[id];
                if(tree[np].cnt == 3) {
                    int cur = tree[p].cnt;
                    while(cur > id) tree[p].val[cur] = tree[p].val[cur-1], cur--;
                    tree[p].val[id] = tree[np].val[1];

                    tree[p].cnt++;

                    int lp = newnode();
                    tree[np].cnt = 1;
                    tree[lp].cnt = 1;
                    tree[lp].val[0] = tree[np].val[2];
                    tree[lp].son[0] = tree[np].son[2];
                    tree[lp].son[1] = tree[np].son[3];

                    cur = tree[p].cnt;
                    while(cur > id + 1) tree[p].son[cur] = tree[p].son[cur-1], cur--;
                    tree[p].son[id+1] = lp;
                    tree[p].son[id] = np;
                    if(val > tree[np].val[1]) np = lp;
                }
                insert(np,val);
            }


            void display(int p) {
                if(tree[p].cnt == 0) return;
                for(int i=0; i) {
                    printf("%d ", tree[p].val[i]);
                }
                puts("");
                for(int i=0; i<=tree[p].cnt; i++) {
                    display(tree[p].son[i]);
                }
            }

int main(){
            int T;  scanf("%d", &T);
            int cas = 0;
            while(T--) {
                tot = 0;
                int rt = newnode();
                int n;
                scanf("%d", &n);
                for(int i=1; i<=n; i++) {
                    int x;  scanf("%d", &x);
                    if(tree[rt].cnt == 3) {
                        int newle = rt;
                        rt = newnode();
                        int newri = newnode();
                        tree[rt].cnt = 1; tree[rt].val[0] = tree[newle].val[1]; tree[rt].son[0] = newle; tree[rt].son[1] = newri;
                        tree[newri].cnt = 1; tree[newri].val[0] = tree[newle].val[2];
                        tree[newri].son[0] = tree[newle].son[2]; tree[newri].son[1] = tree[newle].son[3];
                        tree[newle].cnt =1;
                    }
                    insert(rt,  x);
                }
                printf("Case #%d:\n", ++cas);
                    display(rt);
            }

            return 0;
}
View Code

 

F. Moving On

G. Factories  

树形DP + 背包

https://blog.csdn.net/dllpXFire/article/details/81085093

https://blog.csdn.net/starlet_kiss/article/details/100176118

问题可以转化为边使用的贡献。

所以对于一个点u,在以u为根的子树中选了几个点,可以算出边的贡献。

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include 
#include  
#include  
#include   
#include   
#include   
#include    
#include    
#include    
#include    <string>
#include    
#include     
#include     
#include     
#include      
#include       
#include       <set>
#include   
#include 
// #include
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;

template
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

/**********showtime************/
            const int maxn = 1e5+9;
            vectormp[maxn];
            int du[maxn];
            ll dp[maxn][109];
            int sz[maxn];
            int n,k;
            bool cmp(pii a, pii b) {
                return sz[a.fi] < sz[b.fi];
            }
            void dfs(int u, int fa) {

                for(int i=1; i<=k; i++) dp[u][i] = inff;
                dp[u][0] = 0;

                if(mp[u].size() == 1 ) {
                    sz[u] = 1;
                    dp[u][1] = 0;
                }
                else sz[u] = 0;

                for(pii p : mp[u]) {
                    int v = p.fi, w = p.se;
                    if(v == fa) continue;
                    dfs(v, u);
                }
                sort(mp[u].begin(), mp[u].end(), cmp);
                //sort下, 快了5s。
                for(pii p : mp[u]) {
                    int v = p.fi, w = p.se;
                    if(v == fa) continue;
                    for(int i = min(k, sz[u]); i>=0; i--) {     //i 表示目前有几个
                        for(int j=0; j<=min(k, sz[v]) &&i + j <= k; j++) {//j表示可以从子树中拿几个
                            dp[u][i + j] = min(dp[u][i+j], dp[v][j] + dp[u][i] + 1ll*w*j*(k-j));
                        }
                    }
                    sz[u] += sz[v];
                }
            }
int main(){
            int T;  scanf("%d", &T);
            int cas = 0;
            while(T--) {
                scanf("%d%d", &n, &k);

                for(int i=1; i<=n; i++) du[i] = 0, mp[i].clear();

                for(int i=1; i) {
                    int u,v,w;
                    scanf("%d%d%d", &u, &v, &w);
                    mp[u].pb(pii(v, w));
                    mp[v].pb(pii(u, w));
                    du[u]++;du[v]++;
                }
                if(k == 1) {
                    printf("Case #%d: %d\n", ++cas, 0);
                    continue;
                }
                if(n == 2) {
                    printf("Case #%d: %d\n", ++cas, mp[1][0].se);
                    continue;
                }
                int rt = 1;
                for(int i=1; i<=n; i++) if(du[i] > 1) rt = i;
                dfs(rt, rt);
                printf("Case #%d: %lld\n", ++cas, dp[rt][k]);
            }

            return 0;
}
View Code

 

H. Fight Against Monsters

I. Bubble Sort

https://www.cnblogs.com/wzgg/p/11453284.html

J. Nested Triangles

K. Vertex Covers

折半枚举 + 高维前缀和(用sosDP枚举父集)

先处理出前半数点的情况,注意去掉不合法的状态。然后对每个状态累加上包含这种状态的父集的DP值。

然后枚举后半数点的情况,对于两半间的边,如果后半数点没选,前半数点就必选。累计答案即可。

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include 
#include  
#include  
#include   
#include   
#include   
#include    
#include    
#include    
#include    <string>
#include    
#include     
#include     
#include     
#include      
#include       
#include       <set>
#include   
#include 
// #include
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;

template
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

/**********showtime************/
            const int maxn = 50;
            int w[maxn], used[maxn];
            vector<int>mp[maxn];
            const int maxm = 1e6+9;
            ll dp[maxm];
int main(){
            int T;  scanf("%d", &T);
            int cas = 0;
            while(T--) {
                int n, m, q;
                scanf("%d%d%d", &n, &m, &q);
                for(int i=1; i<=n; i++) scanf("%d", &w[i]);

                for(int i=1; i<=m; i++) {
                    int u,v;
                    scanf("%d%d", &u, &v);
                    mp[u].pb(v);
                    mp[v].pb(u);
                }
                int Le = n / 2, Ri = n - Le;
                for(int i=0; i < (1 << Le); i++) {
                    int x = i;
                    ll tmp = 1;
                    for(int j=1; j<=Le; j++) {
                        used[j] = x % 2;
                        x = x / 2;
                        if(used[j]) tmp = tmp * w[j] % q;
                    }
                    int flag = 0;
                    for(int j=1; j<=Le; j++) {
                        if(used[j]) continue;
                        int ff = 0;
                        for(int v : mp[j]) {
                            if(v <= Le && used[v] == 0) {
                                ff = 1;
                                break;
                            }
                        }
                        if(ff) {flag = 1; break;}
                    }
                    if(flag) {
                        dp[i] = 0;
                        continue;
                    }
                    dp[i] = tmp;
                }
//                for (int mask = 0; mask < (1<
                ///用sosDP枚举每个状态的父集
                for (int i = 0; i < Le; i++) {
                    for (int mask = 0; mask < (1<) {
                        if(mask&(1<1<1< q;
                    }
                }

                ll ans = 0;

                for(int i=0; i < (1 << Ri); i++) {
                    int x = i;
                    ll tmp = 1;
                    for(int j=1; j<=Ri; j++) {
                        int id = j + Le;
                        used[id] = x % 2;
                        x = x / 2;
                        if(used[id]) tmp = tmp * w[id] % q;
                    }

                    int flag = 0;
                    for(int j=1; j<=Ri; j++) {
                        int id = j + Le;
                        if(used[id]) continue;
                        int ff = 0;
                        for(int v : mp[id]) {
                            if(v > Le && used[v] == 0) {
                                ff = 1;
                                break;
                            }
                        }
                        if(ff) {flag = 1; break;}
                    }
                    if(flag) continue;

                    int left = 0;
                    for(int j=1; j<=Ri; j++) {
                        int id = j + Le;
                        if(used[id]) continue;

                        for(int v : mp[id]) {
                            if(v <= Le) {
                                left = left | (1 << (v-1));
                            }
                        }
                    }
//                    cout<< left << " , " << i<
                    ans = (ans + dp[left] * tmp % q )% q;
                }
                printf("Case #%d: %lld\n",++cas,  ans);
                for(int i=1; i<=n; i++) mp[i].clear(), used[i] = 0;
            }
            return 0;
}
View Code

 

 

L. Continuous Intervals

单调栈 + 线段树

参考: https://blog.csdn.net/u013534123/article/details/81164504

首先要想到问题可以转化为求 满足 $max - min + 1 == cnt$ 的区间个数

其中max表示区间最大值,min表示区间最小值,cnt表示区间种类数。

对公式移项 得到$max - min - cnt == -1$。

于是可以枚举区间右端点,计算有多少左端点满足$max - min - cnt == -1$。

/*
* @Author: chenkexing
* @Date:   2019-09-01 21:08:33
* @Last Modified by:   chenkexing
* @Last Modified time: 2019-09-01 22:41:48
* @link:https://nanti.jisuanke.com/t/41296
*/

#include 
#include  
#include  
#include   
#include   
#include   
#include    
#include    
#include    
#include    <string>
#include    
#include     
#include     
#include     
#include      
#include       
#include       <set>
#include   
// #include
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;

template
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

/**********showtime************/

            const int maxn = 1e5+9;
            int a[maxn];    
            stacksbig, ssml;
            map<int, int> pre;
            pii tree[maxn<<2];
            int lazy[maxn << 2];
            void pushup(int rt) {
                if(tree[rt<<1].fi == tree[rt<<1|1].fi) 
                {
                    tree[rt].fi = tree[rt<<1].fi;
                    tree[rt].se = tree[rt<<1].se + tree[rt<<1|1].se;
                }
                else if(tree[rt<<1].fi < tree[rt<<1|1].fi) {
                    tree[rt] = tree[rt<<1];
                }
                else {
                    tree[rt] = tree[rt<<1|1];
                }
            }
            void build(int le, int ri, int rt) {
                lazy[rt] = 0;
                if(le == ri) {
                    tree[rt] = pii(0, 1);
                    return;
                }
                int mid = (le + ri) >> 1;
                build(le, mid ,rt<<1);
                build(mid+1, ri, rt<<1|1);
                pushup(rt);
            }
        
            void pushdown(int le, int ri,int rt) {
                lazy[rt<<1] += lazy[rt];
                lazy[rt<<1|1] += lazy[rt];
                tree[rt<<1].fi += lazy[rt];
                tree[rt<<1|1].fi += lazy[rt];
                lazy[rt] = 0;
            }
            void update(int L, int R, int val, int le, int ri, int rt) {
                if(le >= L && ri <= R) {
                    lazy[rt] += val;
                    tree[rt].fi += val;
                    return;
                }
                int mid = (le + ri) >> 1;
                if(lazy[rt]) pushdown(le, ri, rt);
                if(mid >= L) update(L, R, val, le, mid, rt<<1);
                if(mid < R) update(L, R, val, mid+1, ri, rt<<1|1);
                pushup(rt);
            }

            pii query(int L, int R, int le, int ri, int rt) {
                if(le >= L && ri <= R) {
                    return tree[rt];
                }
                int mid = (le + ri) >> 1;
                pii res = pii(inf, inf);
                if(lazy[rt]) pushdown(le, ri, rt);
                if(mid >= L) {
                    res = query(L, R, le, mid, rt<<1);
                }
                if(mid < R) {
                    pii t = query(L, R, mid+1, ri, rt<<1|1);
                    if(t.fi == res.fi) res.se += t.se;
                    else if(t.fi < res.fi) res = t;
                }
                return res;
            }
int main(){
            int T;  scanf("%d", &T);
            int cas = 0;
            while(T--) {
                int n;  scanf("%d", &n);
                for(int i=1; i<=n; i++) scanf("%d", &a[i]);
                ll ans = 0;
                pre.clear();
                build(1, n, 1);
                while(!sbig.empty()) sbig.pop();
                while(!ssml.empty()) ssml.pop();
                // sbig.push(pii(0, 0));
                // ssml.push(pii(0, 0));
                for(int i=1; i<=n; i++) {
                    
                    pii tmp = pii(0, 0);
                    if(!sbig.empty()) tmp = sbig.top();
                    update(tmp.se+1, i, a[i], 1, n, 1);

                    while(!sbig.empty() && sbig.top().fi <= a[i]) {
                        pii tmp = sbig.top();
                        sbig.pop();
                        pii ff = pii(0, 0);
                        if(!sbig.empty()) ff = sbig.top();
                        update(ff.se+1,tmp.se , a[i] - tmp.fi, 1, n, 1);
                    }
                    sbig.push(pii(a[i], i));


                    tmp = pii(0, 0);
                    if(!ssml.empty()) tmp = ssml.top();
                    update(tmp.se+1, i, -a[i] , 1, n, 1);

                    while(!ssml.empty() && ssml.top().fi >= a[i]) {
                        pii tmp = ssml.top();
                        ssml.pop();
                        pii ff = pii(0, 0);
                        if(!ssml.empty()) ff = ssml.top();
                        update(ff.se+1,tmp.se , tmp.fi - a[i] , 1, n, 1);
                    }
                    ssml.push(pii(a[i], i));


                    if(pre.count(a[i]) == false) pre[a[i]] = 0;
                    update(pre[a[i]] + 1, i, -1, 1, n, 1);
                    pre[a[i]] = i;
                    pii t = query(1, i, 1, n, 1);
                    if(t.fi == -1) ans += t.se;
                }
                printf("Case #%d: %lld\n", ++cas, ans);
            }
            return 0;       
}
View Code

 

M. Acyclic Orientation

你可能感兴趣的:(2019银川网络赛)