Educational Codeforces Round 19

B 选取很多数让和是一个奇数并且尽可能的大 于是选多个正偶数 选一个最大的奇数 剩下的奇数sort之后从大向小成对的选和是正数的

C 给一个栈做中转让完全转移一个串 使它的字典序最小 可以想到肯定是先选a..z 所以依次直接提取这个串的a...z 两个a中间的字母全部无脑压站  每次枚举到一个当前的最小字母 就看看栈顶能不能pop出来 

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<string>
#include<vector>
#include<queue>
#include<iostream>
using namespace std ;
#define L long long
#define pb push_back

char s[100050] ;

char a[100050] ;
char ans[100050] ;

int r ;
int l ;

int main() {
    scanf("%s" , s) ;
    int len = strlen(s) ;
    r = -1 ;
    l = 0 ;
    int res = 0;
    for(int i = 0 ; i < 26 ; i ++ ) {
        char c = 'a' + i ;
        while(r >= 0 && a[r] <= c) {
            ans[res] = a[r] ;
            r -- ;
            res ++ ;
        }
        bool you = false ;
        int w = 0 ;
        for(int j = l ; j < len ; j ++ ) {
            if(s[j] == c) {
                w = j ;
                you = true ;
            }
        }
        if(you == true) {
            for(int j = l ; j <= w ; j ++ ) {
                if(s[j] == c) {
                    ans[res] = c ;
                    res ++ ;
                }
                else {
                    r ++ ;
                    a[r] = s[j] ;
                }
            }
            l = w + 1 ;
        }
    }
    while(r >= 0) {
        ans[res] = a[r] ;
        res ++ ;
        r -- ;
    }
    for(int i = 0 ; i < len ; i ++ ) printf("%c" , ans[i]) ;
    printf("\n") ;
}

D 给出一个二叉搜索树 对每一个值 都从根节点开始找 比根节点小就到左边 大就到右边 相等就是找到了 问最后有多少个值找不到

它只问能不能找到 没说判断二叉搜索树有多少个点是放错了的的 并且如果有多个2 我可以找到任意一个 对于其他的2来说 2也是被找到的 即我们只管值 不管点

两个优先队列维护一个点到它上面的祖先节点的所有的值的最大值和最小值 用on数组来辅助 

之所以开两个优先队列 是为了分别存 它的祖先节点是往左走的还是往右的 可以发现如果这个点的一个祖先到这个点是往左走的 而这个点比祖先大 那这个点是无法被到达的

最后再判断一个每个值能否被到达 毕竟虽然一个点不可能被到达 但是如果有相同值的点可行 那么这个值就也可以被到达

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<queue>
#include<algorithm>
#define pb push_back
#define L long long
using namespace std;

struct node1{
    int x , id ;
    bool operator < (const node1 & a) const {
        return a.x < x ;
    }
};
struct node2{
    int x , id ;
    bool operator < (const node2 & a) const {
        return a.x > x ;
    }
};
priority_queue<node1>q1 ; /// less
priority_queue<node2>q2 ; /// greater
bool on[100050][3] ;

map<int , int > mp ;
bool tg[100050] ;

int n ;
vector<int > q[100050] ;
int b[100050] ;
int rd[100050] ;

int ans ;

void dfs(int u) {
    while(q1.size() > 0 && on[q1.top().id][1] == false) q1.pop() ;
    while(q2.size() > 0 && on[q2.top().id][2] == false) q2.pop() ;

    int v1 = q[u][0] ; int v2 = q[u][1] ;
    bool ok = true ;
    if(q1.size() > 0) {
        if(q1.top().x < b[u]) ok = false ;
    }
    if(q2.size() > 0) {
        if(q2.top().x > b[u]) ok = false ;
    }
    if(ok == false) {
        ans ++ ;
        tg[u] = false ;
    }
    else {
        mp[b[u]] ++ ;
    }
    node1 tmp ; tmp.x = b[u] ; tmp.id = u ; q1.push(tmp) ;
    on[u][1] = true ;
    if(v1 != -1) dfs(v1) ;
    on[u][1] = false ;
    node2 tmp2 ; tmp2.x = b[u] ; tmp2.id = u ; q2.push(tmp2) ;
    on[u][2] = true ;
    if(v2 != -1) dfs(v2) ;
    on[u][2] = false ;
}

int main () {
    mp.clear() ;
    memset(tg , true , sizeof(tg)) ;
    scanf("%d" , &n) ;
    memset(on , false , sizeof(on)) ;
    memset(rd , 0 , sizeof(rd)) ;
    for(int i = 1 ; i <= n ; i ++ ) q[i].clear() ;
    for(int i = 1 ; i <= n ; i ++ ) {
        scanf("%d" , &b[i]) ;
        int x1,x2 ;
        scanf("%d%d",&x1,&x2);
        q[i].pb(x1) ; q[i].pb(x2) ;
        if(x1!=-1)rd[x1]++ ;
        if(x2!=-1)rd[x2]++ ;
    }
    ans = 0 ;
    for(int i = 1 ; i <= n ; i ++ ) {
        if(rd[i] == 0) {
            dfs(i) ;
        }
    }
    for(int i = 1 ; i <= n ; i ++ ) {
        if(tg[i] == false) {
            if(mp[b[i]] > 0) {
                ans -- ;
            }
        }
    }
    printf("%d\n" , ans) ;
}

E 给出一个数字增长的规律 问多少步可以跳出来 

可以发现如果暴力着去跳的话 如果a[i]和k全部都是1肯定会超时 而如果要写个dp的话 时间和空间都不怎么允许

所以采取一个 小数据 k <= 100的时候 写个dp 复杂度是nk  k>100的时候直接暴力 1000步肯定可以跳完

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<string>
#include<vector>
#include<queue>
#include<iostream>
using namespace std ;
#define L long long
#define pb push_back

int n , q ;

int a[100050] ;
int dp[100050][105] ;

int main () {
    cin >> n ;
    for(int i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]) ;
    for(int i = n ; i >= 1 ; i -- ) {
        for(int k = 1 ; k <= 100 ; k ++ ) {
            if(i + k + a[i] > n) {
                dp[i][k] = 1 ;
            }
            else {
                dp[i][k] = dp[i+a[i]+k][k] + 1 ;
            }
        }
    }
    cin >> q ;
    while(q -- ) {
        int p , k ;
        scanf("%d%d" , &p , &k) ;
        if(k <= 100) {
            printf("%d\n" , dp[p][k]) ;
        }
        else {
            int ans = 0 ;
            while(p <= n) {
                ans ++ ;
                p += a[p] ;
                p += k ;
            }
            printf("%d\n" , ans) ;
        }
    }
}

东北赛被吊打很不开心。。一个贪心的题不会做 也很久没有打cf了 树形dp啥的可能也不太熟练了 还是要多练习

想想还是很不甘心 就像宁波铁回来一样。。还是要多做几道题 提高一下自己的姿势水平。。不要只会说学逗唱。。

在寝室补题 笔记本的键盘不好用 自己的cherry小茶放在了实验室 于是拿出了刚入学用的键盘来敲题

我的老朋友 好久不见~

posted @ 2017-05-17 00:30  天翎月  阅读(123)  评论(0编辑  收藏  举报