hihocoder挑战赛20小记

来源:互联网 发布:西门子plc编程指令详解 编辑:程序博客网 时间:2024/04/29 06:25

2016.11.4
晚上六点点开了一场看上去通过人数比较多的hihoround(20),virtual participate了一下。感觉这场还是比较友好的,和我以前做的hihoround只能做一题,或者爆零不一样。在两个小时里写了3个题(A,B,C),D看上去像是个经典问题,但从来没写过(几何基本等于残疾),便直接放弃了。

这场是岛娘出的,我还以为是ta朋友出的。
感觉题挺不错。题解写的也不错。
官方题解:http://hihocoder.com/discuss/question/3329

我讲讲我的做法吧。
A:入门的区间最大值了,可能是岛娘觉得像CF一样出个很水的没代码量的A没意思,就让大家写个线段树或者ST了。
我的代码:

#include <cstdio>#include <algorithm>#include <cstring>#include <iostream>using namespace std;const int maxn = 1e5 + 5;#define lson o * 2,l,mid#define rson o * 2 + 1,mid + 1,rstruct segmentTree{    int maxv[maxn << 2];    void pushup(int o){        maxv[o] = max(maxv[o << 1],maxv[o << 1 | 1]);    }    void build(int o,int l,int r){        if(l == r) {maxv[o] = 0;return;}        int mid = (l + r) >> 1;        build(lson);        build(rson);        pushup(o);    }    void update(int o,int l,int r,int p,int val){        if(l == r) {maxv[o] = max(maxv[o],val);return;}        int mid = (l + r) >> 1;        if(p <= mid) update(lson,p,val);        else update(rson,p,val);        pushup(o);    }    int query(int o,int l,int r,int ql,int qr){        if(ql <= l && r <= qr){            return maxv[o];        }        int ans = 0;        int mid = (l + r) >> 1;        if(ql <= mid){            ans = max(ans,query(lson,ql,qr));        }        if(qr > mid){            ans = max(ans,query(rson,ql,qr));        }        return ans;    }}tree;int n,m;int main(){    cin >> n >> m;    tree.build(1,1,maxn - 5);    for(int i = 1;i <= n;i++){        int t,v;        scanf("%d%d",&t,&v);        tree.update(1,1,maxn - 5,t,v);    }    int ans;    for(int i = 1;i <= m;i++){        int a,b;scanf("%d%d",&a,&b);        ans = tree.query(1,1,maxn - 5,a,b);        if(ans == 0) printf("None\n");        else printf("%d\n",ans);    }    return 0;}

B:
这是一个括号匹配类型的问题。仔细分析发现,其实可以是个dp。
dp[i]=dp[left]+1,left使s[left+1]s[i]i,ansdp[i],O(n2)dpleft,depth,pre(depth((()())),,,.线)

代码:

#include <cstdio>#include <algorithm>#include <iostream>#include <cstring>#include <stack>using namespace std;const int maxn = 1e6 + 5;int dp[maxn];int num[maxn];char s[maxn];char Stack[maxn];int top;int main(){    scanf("%s",s + 1);    int n = strlen(s + 1);    top = 0;    memset(num,0,sizeof(num));    memset(dp,0,sizeof(dp));    for(int i = 1;i <= n;i++){        if(s[i] == '('){//左括号压栈            dp[i] = 0;            Stack[++top] = '(';        }else{            if(Stack[top] == ')' || top == 0){                dp[i] = 0;                Stack[++top] = ')';            }else{//关键,匹配了,则层数减少,便把这一层的答案置0                num[top] = 0;                top--;                dp[i] = num[top] + 1;                num[top] = dp[i];//更新这一层答案            }        }    }    long long ans = 0;    for(int i = 1;i <= n;i++) ans += dp[i];//cout << dp[i] << " ";    cout << ans << endl;    return 0;}

C:
数位dp。
题解说二分+dp。
其实二分的过程可以包含在dp的过程中了。不错的练手题,推荐数位dp欠缺(比如我)的人写,虽然这个dp代码量不大。

我的代码(严格也不算数位dp了):

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;long long power[20];long long pow8[20];long long k;int d[20];int main(){    power[0] = 1;    pow8[0] = 1;    for(int i = 1;i < 20;i++) power[i] = power[i - 1] * 10LL;    //cout << pow10[18] << endl;    for(int i = 1;i < 20;i++) pow8[i] = pow8[i - 1] * 8LL;    //cout << 9LL * (pow10[18] - pow8[18]) << endl;    cin >> k;    bool flag = false;    bool first = false;    for(int p = 19;p >= 1;p--){        long long sum = 0;        //cout << k << endl;        for(int j = 0;j <= 9;j++){            if(flag){                if(sum + power[p - 1] - ((!first && j == 0) ? 1 : 0 )>= k){                    d[p] = j;                    if(j != 0) first = true;                    k -= sum;                    break;                }else{                    sum = sum + power[p - 1] - (!first && j == 0);                }            }else{                if(j == 4 || j == 7){                    if(sum + power[p - 1] >= k){                        d[p] = j;                        if(j != 0) first = true;                        k -= sum;                        flag = true;                        break;                    }else{                        sum = sum + power[p - 1];                        //if(p == 2) cout << sum << endl;                    }                }else{                    if(sum + power[p - 1] - pow8[p - 1]  >= k){                        d[p] = j;                        if(j != 0) first = true;                        k -= sum;                        break;                    }else{                        sum = sum + power[p - 1] - pow8[p - 1];                        //if(p == 2) cout << sum << endl;                    }                }            }        }    }    first = false;    for(int i = 19;i >= 1;i--){        if(!d[i] && !first) continue;        else{            if(d[i] > 0) first = true;            printf("%d",d[i]);        }    }       return 0;}
0 0
原创粉丝点击