码迷,mamicode.com
首页 > 其他好文 > 详细

Educational Codeforces Round 19

时间:2020-08-19 19:49:08      阅读:61      评论:0      收藏:0      [点我收藏+]

标签:code   turn   记录   +=   i+1   ati   class   注意   end   

Educational Codeforces Round 19??

A. k-Factorization

找出所有质因子,把多的合并一下

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);};

void solve(){
    int n, k;
    cin >> n >> k;
    vector<int> vec;
    for(int i = 2; i  * i <= n; i++){
        if(n%i!=0) continue;
        while(n%i==0){
            n /= i;
            vec.push_back(i);
        }
    }
    if(n!=1) vec.push_back(n);
    if(k>vec.size()) cout << -1 << endl;
    else{
        while(vec.size() > k){
            int x = vec.back();
            vec.pop_back();
            vec.back() *= x;
        }
        for(int x : vec) cout << x << ‘ ‘; cout << endl;
    }
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}

B. Odd sum

\(dp\)一下,\(dp[i][0]\)\(dp[i][1]\)分别表示已经得到的子序列的和为偶数和奇数的情况的最大值

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, A[MAXN], pre[MAXN];
int f[MAXN][2];
void solve(){
    ____();
    cin >> n;
    f[0][1] = -0x3f3f3f3f;
    for(int i = 1; i <= n; i++){
        int x; cin >> x;
        if(x&1){
            f[i][0] = max(f[i-1][0],f[i-1][1]+x);
            f[i][1] = max(f[i-1][1],f[i-1][0]+x);
        }else{
            f[i][0] = max(f[i-1][0],f[i-1][0]+x);
            f[i][1] = max(f[i-1][1],f[i-1][1]+x);
        }
    }
    cout << f[n][1] << endl;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}

C. Minimal string

显然需要贪心选取最小的字母,这个用子序列自动机来做一下,同时维护一个栈,每次找到下一个最小的字母的位置,先和栈顶的字母比较,然后再把这个字母添加到答案里去,把中间中间跳过去的的字符全部加到栈里面去。

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;
char s[MAXN];
int nxt[MAXN][26];
stack<char> stk;
void solve(){
    cin >> s + 1;
    int n = strlen(s+1);
    for(int i = 0; i < 26; i++) nxt[n][i] = MAXN;
    for(int i = n - 1; i >= 0; i--){
        for(int j = 0; j < 26; j++) nxt[i][j] = nxt[i+1][j];
        nxt[i][s[i+1]-‘a‘] = i+1;
    }
    string ret;
    int ptr = 0;
    while(true){
        bool ok = false;
        for(int i = 0; i < 26; i++){
            if(nxt[ptr][i]!=MAXN){
                while(!stk.empty() and stk.top()<=i+‘a‘) ret += stk.top(), stk.pop();
                ret += s[nxt[ptr][i]];
                for(int k = ptr + 1; k < nxt[ptr][i]; k++) stk.push(s[k]);
                ok = true;
                ptr = nxt[ptr][i];
                break;
            }
        }
        if(!ok) break;
    }
    while(!stk.empty()) ret += stk.top(), stk.pop();
    cout << ret << endl;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}

D. Broken BST

从根到某个节点的路径是唯一的,所以我们可以知道从根到查询节点经过哪些点是需要走左儿子,哪些点需要走右儿子,显然走左儿子必须要满足查询节点的值比当前节点的值小,右儿子一定要查询节点的值比当前节点的值大,所以我们可以\(dfd\)过程中记录走左儿子的点的最小值和走右儿子的点的最大值,然后判断查询节点的值是否在可行区间内即可

注意处理值相同的情况

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 ls[MAXN], rs[MAXN], n, root, w[MAXN], ret;
bool vis[MAXN];
map<int,bool> msk;
void dfs(int u, int mi, int ma){
    if(w[u]>=ma and w[u]<=mi) msk[w[u]] = true;
    if(ls[u]!=-1) dfs(ls[u],min(mi,w[u]),ma);
    if(rs[u]!=-1) dfs(rs[u],mi,max(ma,w[u]));
}
void solve(){
    ____();
    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> w[i] >> ls[i] >> rs[i];
        if(ls[i]!=-1) vis[ls[i]] = true;
        if(rs[i]!=-1) vis[rs[i]] = true;
    }
    for(int i = 1; i <= n; i++) if(!vis[i]) root = i;
    dfs(root,0x3f3f3f3f,-1);
    for(int i = 1; i <= n; i++) if(!msk.count(w[i])) ret++;
    cout << ret << endl;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}

E. Array Queries

如果暴力\(dp\)复杂度会很高,复杂度高的原因是会有很多小的\(k\),那么我们预处理出来所有小的\(k\)的答案就好了

设一个\(k\)上限,小于上限预处理,大于等于直接跑,选上限为\(\sqrt n\),复杂度为\(O(q\sqrt n)\)

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;
const int lim = 300;
int n, A[MAXN], f[MAXN][lim];
void solve(){
    ____();
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> A[i];
    for(int k = 1; k < lim; k++){
        for(int i = n; i >= 1; i--){
            if(i+A[i]+k>n) f[i][k] = 1;
            else f[i][k] = 1 + f[i+A[i]+k][k];
        }
    }
    int q; cin >> q;
    while(q--){
        int p, k; cin >> p >> k;
        if(k < lim) cout << f[p][k] << endl;
        else{
            int __count = 0;
            while(p<=n) p = p+A[p]+k, __count++;
            cout << __count << endl;
        }
    }
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}

F.?Mice and Holes

显然需要把所有老鼠和洞按位置先排序

然后\(dp[i][j]\)表示考虑前\(i\)个洞口,安排了\(j\)只老鼠的最小距离和

那么转移方程就长这样:

\[dp[i][j] = \min_{k}\{dp[i-1][k]+S[j]-S[k]\},j-k<=c_i \]

其中\(S[i]\)表示前\(i\)个老鼠到当前枚举的洞口的距离和,\(c_i\)表示\(i\)号洞口的容量

由于转移方程中\(S[j]\)是定值,可以用单调队列来维护

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 = 5007;
typedef long long int LL;
int n, m, x[MAXN];
LL f[2][MAXN], dis[MAXN];
pair<int,int> hole[MAXN];
pair<LL,int> que[MAXN];
void solve(){
    ____();
    cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> x[i];
    for(int i = 1; i <= m; i++) cin >> hole[i].first >> hole[i].second;
    sort(x+1,x+1+n); sort(hole+1,hole+1+m);
    memset(f,0x3f,sizeof(f));
    int tag = 1; f[0][0] = 0;
    for(int i = 1; i <= m; i++, tag ^= 1){
        memset(f[tag],0x3f,sizeof(f[tag]));
        f[tag][0] = 0;
        int d = hole[i].first, c = hole[i].second;
        for(int j = 1; j <= n; j++) dis[j] = dis[j-1] + abs(d-x[j]);
        int head = 0, tail = -1;
        que[++tail] = {0,0};
        for(int j = 1; j <= n; j++){
            LL dp = f[tag^1][j] - dis[j];
            while(head<=tail and que[tail].first>=dp) tail--;
            que[++tail] = {dp,j};
            if(j-que[head].second>c) head++;
            f[tag][j] = que[head].first + dis[j];
        }
    }
    cout << (f[tag^1][n] < 0x3f3f3f3f3f3f3f3f ? f[tag^1][n] : -1) << endl;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}

Educational Codeforces Round 19

标签:code   turn   记录   +=   i+1   ati   class   注意   end   

原文地址:https://www.cnblogs.com/kikokiko/p/13516939.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!