《Deltix Round, Autumn 2021 (open for everyone, rated, Div. 1 + Div. 2)》

感觉这场题面有点绕

A:先把能除2的都除2,然后最后再把最大的不断翻倍即可

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double ld;
typedef pair<int,int> pii;
const int N = 2e3 + 5;
const int M = 1e4 + 5;
const LL Mod = 1e9 + 7;
#define rep(at,am,as) for(int at = am;at <= as;++at)
#define ret(at,am,as) for(int at = am;at >= as;--at)
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;
inline long long ADD(long long x,long long y) {
    if(x + y < 0) return ((x + y) % Mod + Mod) % Mod;
    return (x + y) % Mod;
}
inline long long MUL(long long x,long long y) {
    if(x * y < 0) return ((x * y) % Mod + Mod) % Mod;
    return x * y % Mod;
}
inline long long DEC(long long x,long long y) {
    if(x - y < 0) return (x - y + Mod) % Mod;
    return (x - y) % Mod;
}

int n,a[N];
void solve() {
    scanf("%d",&n);
    for(int i = 1;i <= n;++i) scanf("%d",&a[i]);
    int cnt = 0,pos;
    LL mx = 0;
    for(int i = 1;i <= n;++i) {
        while(a[i] % 2 == 0) a[i] /= 2,++cnt;
        if(a[i] * 1LL > mx) mx = a[i],pos = i;
    }
    LL ans = 0;
    for(int i = 1;i <= n;++i) {
        if(i != pos) ans += a[i];
        else {
            LL tmp = a[i];
            for(int j = 1;j <= cnt;++j) tmp *= 2;
            ans += tmp;
        }
    }
    printf("%lld\n",ans);

}   
int main() {
    int _;
    for(scanf("%d",&_);_;_--) {
        solve();
    }
    //system("pause");
    return 0;
}
View Code

B:演爆了。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double ld;
typedef pair<int,int> pii;
const int N = 1e5 + 5;
const int M = 1e4 + 5;
const LL Mod = 1e9 + 7;
#define rep(at,am,as) for(int at = am;at <= as;++at)
#define ret(at,am,as) for(int at = am;at >= as;--at)
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;
inline long long ADD(long long x,long long y) {
    if(x + y < 0) return ((x + y) % Mod + Mod) % Mod;
    return (x + y) % Mod;
}
inline long long MUL(long long x,long long y) {
    if(x * y < 0) return ((x * y) % Mod + Mod) % Mod;
    return x * y % Mod;
}
inline long long DEC(long long x,long long y) {
    if(x - y < 0) return (x - y + Mod) % Mod;
    return (x - y) % Mod;
}

char s[N];
int n,q;
bool check(int id,char t) {
    if(id <= n - 2 && t == 'a' && s[id] == 'b' && s[id + 1] == 'c') return true;
    if(id <= n - 1 && id >= 2 && t == 'b' && s[id - 2] == 'a' && s[id] == 'c') return true;
    if(id >= 3 && t == 'c' && s[id - 2] == 'b' && s[id - 3] == 'a') return true;
    return false;
}

void solve() {
    scanf("%d %d",&n,&q);
    cin >> s;
    int ans = 0;
    for(int i = 0;i < n;++i) {
        if(i + 2 >= n) break;
        if(s[i] == 'a' && s[i + 1] == 'b' && s[i + 2] == 'c') ans++;
    }
    while(q--) {
        int id;
        string t;
        cin >> id >> t;
        if(t[0] == s[id - 1]) {printf("%d\n",ans);continue;}
        if(check(id,t[0])) ans++;
        if(check(id,s[id - 1])) ans--;
        printf("%d\n",ans);
        s[id - 1] = t[0];
    }

}   
int main() {
    // int _;
    // for(scanf("%d",&_);_;_--) {
        solve();
    //}
  //  system("pause");
    return 0;
}
View Code

C:倒着dp即可,用e来判断

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double ld;
typedef pair<int,int> pii;
const int N = 2e5 + 5;
const int M = 1e6 + 5;
const LL Mod = 1e9 + 7;
#define rep(at,am,as) for(int at = am;at <= as;++at)
#define ret(at,am,as) for(int at = am;at >= as;--at)
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;
inline long long ADD(long long x,long long y) {
    if(x + y < 0) return ((x + y) % Mod + Mod) % Mod;
    return (x + y) % Mod;
}
inline long long MUL(long long x,long long y) {
    if(x * y < 0) return ((x * y) % Mod + Mod) % Mod;
    return x * y % Mod;
}
inline long long DEC(long long x,long long y) {
    if(x - y < 0) return (x - y + Mod) % Mod;
    return (x - y) % Mod;
}

int n,e,a[M];
bool vis[M];
int prime[M],tot = 0;
void init() {
    for(int i = 2;i < M;++i) {
        if(!vis[i]) prime[++tot] = i;
        for(int j = 1;j <= tot && prime[j] * i < M;++j) {
            vis[prime[j] * i] = 1;
            if(i % prime[j] == 0) break;
        }
    }
}
int dp[M],cnt[M];//0 - not 1
void solve() {
    scanf("%d %d",&n,&e);
    for(int i = 1;i <= n;++i) scanf("%d",&a[i]);
    for(int i = 1;i <= (n + e + 5);++i) dp[i] = cnt[i] = 0;
    LL ans = 0;
    ret(i,n,1) {
        cnt[i] = cnt[i + e] + 1;
        if(a[i] == 1) {
            dp[i] = dp[i + e];
            if(dp[i] != 0) {
                if(vis[a[dp[i]]]) continue;
                if(dp[dp[i] + e] == 0 || dp[i] + e > n) ans += cnt[dp[i]];
                else {
                    ans += cnt[dp[i]] - cnt[dp[dp[i] + e]];
                }
            }
        }
        else {
            if(!vis[a[i]]) {
                if(i + e <= n) {
                    if(dp[i + e] == 0) ans += cnt[i + e];
                    else {
                        ans += cnt[i] - cnt[dp[i + e]] - 1;
                    }
                }
            }
            dp[i] = i;
        }
    }
    printf("%lld\n",ans);

}   
int main() {
    init();
    int _;
    for(scanf("%d",&_);_;_--) {
        solve();
    }
   // system("pause");
    return 0;
}
View Code

D:什么逆天题意。

多的边直接连其他连通块即可。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double ld;
typedef pair<int,int> pii;
const int N = 1e3 + 5;
const int M = 1e6 + 5;
const LL Mod = 1e9 + 7;
#define rep(at,am,as) for(int at = am;at <= as;++at)
#define ret(at,am,as) for(int at = am;at >= as;--at)
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;
inline long long ADD(long long x,long long y) {
    if(x + y < 0) return ((x + y) % Mod + Mod) % Mod;
    return (x + y) % Mod;
}
inline long long MUL(long long x,long long y) {
    if(x * y < 0) return ((x * y) % Mod + Mod) % Mod;
    return x * y % Mod;
}
inline long long DEC(long long x,long long y) {
    if(x - y < 0) return (x - y + Mod) % Mod;
    return (x - y) % Mod;
}

int fa[N],ans[N],sz[N];
int Find(int x) {return x == fa[x] ? x : fa[x] = Find(fa[x]);}
bool vis[N][N];
void solve() {
    int n,d;scanf("%d %d",&n,&d);
    for(int i = 1;i <= n;++i) fa[i] = i,sz[i] = 1;
    int cnt = 0;
    while(d--) {
        int ans = 0;
        int x,y;scanf("%d %d",&x,&y);
        int xx = Find(x),yy = Find(y);
        vector<int> vec;
        if(xx != yy) {
            fa[xx] = yy,sz[yy] += sz[xx];
        }
        else cnt++;
        rep(i,1,n) if(i == Find(i)) vec.push_back(sz[i]);
        sort(vec.begin(),vec.end(),greater<int>());
        rep(i,1,min((int)vec.size(),cnt + 1)) ans += vec[i - 1]; 
        printf("%d\n",ans - 1);
    }

}   
int main() {
    //int _;
    //for(scanf("%d",&_);_;_--) {
        solve();
    //}
    //system("pause");
    return 0;
}
View Code

E:这题还是挺不错的。

线段树上维护一个dp。

首先我们考虑一下状压一下状态,第0位代表a,第1位代表b,第2位代表c,第3位代表ab,第4位代表bc。

dp[i] - 表示序列中只包含状态i的情况。

首先问题就是为什么只有这几种情况,因为只有他们对答案有影响,其他的都可以当场什么状态都没的情况即0。

然后就是两个序列合并之后产生的情况,需要充分考虑,然后对于ab这种,其实a和b状态必定包含在里面,所以必须要算上。

合并的时候就是dp[i][j] = min{dp[i][k] + dp[k][j]},类似Floyd。

有点像DFA上的Floyd.

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double ld;
typedef pair<int,int> pii;
const int N = 1e5 + 5;
const int M = 1e6 + 5;
const LL Mod = 1e9 + 7;
#define rep(at,am,as) for(int at = am;at <= as;++at)
#define ret(at,am,as) for(int at = am;at >= as;--at)
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;
inline long long ADD(long long x,long long y) {
    if(x + y < 0) return ((x + y) % Mod + Mod) % Mod;
    return (x + y) % Mod;
}
inline long long MUL(long long x,long long y) {
    if(x * y < 0) return ((x * y) % Mod + Mod) % Mod;
    return x * y % Mod;
}
inline long long DEC(long long x,long long y) {
    if(x - y < 0) return (x - y + Mod) % Mod;
    return (x - y) % Mod;
}

int n,q;
char s[N];
struct Node{int L,r,dp[1 << 5];}node[N << 2];//0 - a,1 - b,2 - c,3 - ab,4 - bc
int Merge[1 << 5][1 << 5];
bool ishav(int i,int k) {
    if((i >> k) & 1) return true;
    else return false;
}
bool judge(int i,int j) {
    if(ishav(i,0) && ishav(j,4)) return false;
    if(ishav(i,3) && (ishav(j,4) || ishav(j,2))) return false;
    return true;
}
void init() {
    rep(i,0,(1 << 5) - 1) {
        rep(j,0,(1 << 5) - 1) {
            if(!judge(i,j)) Merge[i][j] = -1;
            else {
                rep(k,0,4) if(ishav(i,k) || ishav(j,k)) Merge[i][j] |= (1 << k);
                if(ishav(i,0) && ishav(j,1)) Merge[i][j] |= (1 << 3);
                if(ishav(i,1) && ishav(j,2)) Merge[i][j] |= (1 << 4);
                if(ishav(i,3) || ishav(j,3)) Merge[i][j] |= (1 << 0),Merge[i][j] |= (1 << 1);
                if(ishav(i,4) || ishav(j,4)) Merge[i][j] |= (1 << 1),Merge[i][j] |= (1 << 2);
            }
        }
    }
    // rep(i,0,(1 << 5) - 1) {
    //     rep(j,0,(1 << 5) - 1) {
    //         printf("mask[%d][%d] is %d\n",i,j,Merge[i][j]);
    //     } 
    // }
}
void Pushup(int idx) {
    int ls = idx << 1,rs = idx << 1 | 1;
    rep(i,0,(1 << 5) - 1) node[idx].dp[i] = INF;
    rep(i,0,(1 << 5) - 1) {
        rep(j,0,(1 << 5) - 1) {
            if(Merge[i][j] == -1) continue;
            node[idx].dp[Merge[i][j]] = min(node[idx].dp[Merge[i][j]],node[ls].dp[i] + node[rs].dp[j]);
        }
    }
}
void build(int L,int r,int idx) {
    node[idx].L = L,node[idx].r = r;
    rep(i,0,(1 << 5) - 1) node[idx].dp[i] = INF;
    if(L == r) {
        int val = s[L -1] - 'a';
        node[idx].dp[1 << val] = 0;
        node[idx].dp[0] = 1;
        return ;
    }
    int mid = (L + r) >> 1;
    build(L,mid,idx << 1);
    build(mid + 1,r,idx << 1 | 1);
    Pushup(idx);
}
void modify(int x,char c,int idx) {
    if(node[idx].L == node[idx].r) {
        rep(i,0,(1 << 5) - 1) node[idx].dp[i] = INF;
        int val = c - 'a';
        node[idx].dp[1 << val] = 0;
        node[idx].dp[0] = 1; 
        return ;
    }
    int mid = (node[idx].L + node[idx].r) >> 1;
    if(mid >= x) modify(x,c,idx << 1);
    else modify(x,c,idx << 1 | 1); 
    Pushup(idx);
}
void solve() {
    init();
    scanf("%d %d",&n,&q);
    scanf("%s",s);
    build(1,n,1);
    while(q--) {
        int x;char c;
        scanf("%d",&x);getchar();
        c = getchar();
        if(s[x - 1] != c) modify(x,c,1),s[x - 1] = c;
        int ans = INF;
        rep(i,0,(1 << 5) - 1) ans = min(ans,node[1].dp[i]);
        printf("%d\n",ans);
    }
}   
int main() {
    //int _;
    //for(scanf("%d",&_);_;_--) {
        solve();
    //}
    system("pause");
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zwjzwj/p/15631054.html