• 2019-2020nowcoder牛客寒假基础3


    本校大佬阿珂了的时候我还在模拟线段树,虽然还是在最后时间内卡进去了,基础不好呀,说明还是要不好高骛远了,见到数论就不想动不晓得是是自以为跟哪个学长学的,真想开口说自己也是一名数论选手。

    A.牛牛的DRB迷宫I

    简单DP,一个B点可以向下或者是向右做出贡献,其他只能一个方向,忘记取modwa+1,ce+1

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <queue>
    #include <set>
    #include <map>
    #include <stack>
    
    using namespace std;
    #define scd(a) scanf("%d",&a)
    #define scdd(a,b) scanf("%d%d",&a,&b)
    #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
    #define scl(a) scanf("%lld",&a)
    #define scll(a,b) scanf("%lld%lld",&a,&b)
    #define prl(a) printf("%lld
    ",a)
    #define prd(a) printf("%d
    ",a)
    #define prf(a) printf("%lf
    ",a)
    #define ptd(a) printf("%d ",a)
    #define scf(a) scanf("%lf",&a)
    #define scff(a,b) scanf("%lf%lf",&a,&b)
    #define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
    #define rint register int
    #define mem(a) memset(a,0,sizeof(a))
    #define rush() int T;scd(T);while(T--)
    #define lc(i) (i<<1)
    #define rc(i) (i<<1|1)
    #define mp make_pair
    typedef long long ll;
    typedef double db;
    inline int read() {char c=getchar();int x=0,f=1;while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}return x*f;}
    const int maxn = 100 + 10;
    const int mod = 1e9 + 7;
    int dp[maxn][maxn];
    char s[maxn][maxn];
    int main() {
        int n = read(),m = read();
        for (int i = 1 ; i <= n; ++i) scanf("%s", s[i]+1);
        dp[1][1] = 1;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                if (s[i][j] == 'R') {
                    dp[i][j+1] += dp[i][j];
                    dp[i][j+1]%=mod;
                }
                else if (s[i][j] == 'D'){
                    dp[i+1][j] += dp[i][j];
                    dp[i+1][j]%=mod;
                }
                else {
                    dp[i][j+1] += dp[i][j];dp[i][j+1]%=mod;
                    dp[i+1][j] += dp[i][j];dp[i+1][j]%=mod;
                }
            }
        }
        prd(dp[n][m]%mod);
        return 0;
    }
    View Code

    B.牛牛的DRB迷宫II

    emmmm,2*2的可以把左上角的数字左移一位,把二进制数字分解,哪一位上有就建立一个通道到最右边,然后直接跑到右下角,或者是把通道建到最下面,再在最下面建一个一直往右跑的通道。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <stack>
    #include <queue>
    #include <vector>
    #include <set>
    using namespace std;
    #define scd(a) scanf("%d",&a)
    #define scdd(a,b) scanf("%d%d",&a,&b)
    #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
    #define scl(a) scanf("%lld",&a)
    #define scll(a,b) scanf("%lld%lld",&a,&b)
    #define prl(a) printf("%lld
    ",a)
    #define prd(a) printf("%d
    ",a)
    #define prf(a) printf("%lf
    ",a)
    #define ptd(a) printf("%d ",a)
    #define scf(a) scanf("%lf",&a)
    #define scff(a,b) scanf("%lf%lf",&a,&b)
    #define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
    #define rint register int
    #define mem(a) memset(a,0,sizeof(a))
    #define rush() int T;scd(T);while(T--)
    #define lc(i) (i<<1)
    #define rc(i) (i<<1|1)
    #define mp make_pair
    #define scs(x) scanf("%s", x)
    typedef long long ll;
    typedef double db;
    inline int read() {
        char c=getchar();
        int x=0,f=1;
        while(c<'0'||c>'9') {
            if(c=='-')f=-1;
            c=getchar();
        }
        while(c>='0'&&c<='9') {
            x=x*10+c-'0';
            c=getchar();
        }
        return x*f;
    }
    const int maxn = 1e2+2;
    const int MOD = 1e9+7;
    const double Pi = acos(-1.0);
    const double eps = 1e-6;
    #define mid ((l+r)>>1)
    char mep[maxn][maxn];
    void Init(){
        for (int i = 0; i < 55; ++i) {
            mep[i][i] = 'B';
            for (int j = i + 2; j < 55; ++j) 
                mep[j][i] = 'D';
            for (int j = i + 2; j < 55; ++j)
                mep[i][j] = 'R';
            mep[i+1][i] = 'R';
            mep[i][i+1] = 'D';
        }
    //    for (int i = 0; i < 50; ++i)
    //    {    for (int j = 0; j < 50; ++j)
    //            printf("%c ",mep[i][j]);
    //        puts("");
    //    }
    }
    int main()
    {
        Init();
        int n = read();
        int count = 0;
        while (n) {
            if (n&1){
                mep[count][count+1]='B';
            }
            count++;
            n>>=1;
        }
        for (int i = 0; i < 50; ++i) mep[i][49] = 'B';
        mep[49][48]='D';mep[48][48]='D';
        cout<<50<<" "<<50<<endl;
        for (int i = 0; i < 50; ++i)
        {    for (int j = 0; j < 50; ++j)
                printf("%c",mep[i][j]);
            puts("");
        }
        return 0;
    }
    View Code

    C.牛牛的数组越位

    不说了,模拟题一小时,晕死了

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <queue>
    #include <set>
    #include <map>
    #include <stack>
     
    using namespace std;
    #define scd(a) scanf("%d",&a)
    #define scdd(a,b) scanf("%d%d",&a,&b)
    #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
    #define scl(a) scanf("%lld",&a)
    #define scll(a,b) scanf("%lld%lld",&a,&b)
    #define prl(a) printf("%lld
    ",a)
    #define prd(a) printf("%d
    ",a)
    #define prf(a) printf("%lf
    ",a)
    #define ptd(a) printf("%d ",a)
    #define scf(a) scanf("%lf",&a)
    #define scff(a,b) scanf("%lf%lf",&a,&b)
    #define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
    #define rint register int
    #define mem(a) memset(a,0,sizeof(a))
    #define rush() int T;scd(T);while(T--)
    #define lc(i) (i<<1)
    #define rc(i) (i<<1|1)
    #define mp make_pair
    typedef long long ll;
    typedef double db;
    inline int read() {char c=getchar();int x=0,f=1;while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}return x*f;}
    const int maxn = 2e7 + 10;
    const int mod = 1e9 + 7;
    int n,m,p;
    int a[maxn];
    int main() {
        rush(){
            scddd(n,m,p);
            ll lim = n * m;
            for (int i = 0; i < lim; ++i) a[i] = 0;
            int state = 0;
            while (p--) {
                int x,y,val;scddd(x,y,val);
    //            if(state==2)continue;
                int pos = x * m + y;
                if (x < 0 || y < 0 || x >= n || y >= m) {
                    state = max(state,1);
                }
                if (pos < 0 || pos >= lim) {
                    state = max(state,2);
                }
                a[pos] = val;
            }
            if (state == 2) {
                puts("Runtime error");
            }
            else {
                int p = 0;
                for (int i = 0; i < n; ++i)
                {
                    for (int j = 0; j < m; ++j)
                        printf("%d ", a[p++]);
                    puts("");
                }
                if(state==1)
                    puts("Undefined Behaviour");
                else 
                    puts("Accepted");
            }
        }
        return 0;
    }
    View Code

    D.牛牛与二叉树的数组存储

    建立一颗二叉树瞎搞就好了

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <queue>
    #include <set>
    #include <map>
    #include <stack>
    
    using namespace std;
    #define scd(a) scanf("%d",&a)
    #define scdd(a,b) scanf("%d%d",&a,&b)
    #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
    #define scl(a) scanf("%lld",&a)
    #define scll(a,b) scanf("%lld%lld",&a,&b)
    #define prl(a) printf("%lld
    ",a)
    #define prd(a) printf("%d
    ",a)
    #define prf(a) printf("%lf
    ",a)
    #define ptd(a) printf("%d ",a)
    #define scf(a) scanf("%lf",&a)
    #define scff(a,b) scanf("%lf%lf",&a,&b)
    #define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
    #define rint register int
    #define mem(a) memset(a,0,sizeof(a))
    #define rush() int T;scd(T);while(T--)
    #define lc(i) (i<<1)
    #define rc(i) (i<<1|1)
    #define mp make_pair
    typedef long long ll;
    typedef double db;
    inline int read() {char c=getchar();int x=0,f=1;while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}return x*f;}
    const int maxn = 1e5 + 10;
    const int mod = 1e9 + 7;
    int a[maxn << 2];
    struct node {
        int fa, l, r;
    }tree[maxn << 2];
    int sz = 0;int n;
    void dfs(int u, int f) {
        if(u>n)return;
        if(a[u]==0)return;
        if(a[u]==-1)return;
        tree[a[u]].fa = a[f];if(tree[a[u]].fa == 0)tree[a[u]].fa = -1;
        tree[a[u]].l = a[lc(u)];if (tree[a[u]].l==0)tree[a[u]].l=-1;
        tree[a[u]].r = a[rc(u)];if (tree[a[u]].r==0)tree[a[u]].r=-1;
        dfs(lc(u),u);
        dfs(rc(u),u);
    }
    int main() {
        scd(n);a[0]=-1;
        for (int i = 1; i <= n; ++i) scd(a[i]), sz = max(sz,a[i]);
        dfs(1, 0);
        printf("The size of the tree is %d
    ",sz);
        printf("Node %d is the root node of the tree
    ", a[1]);
        for (int i = 1; i <= sz; ++i) {
            printf("The father of node %d is %d, the left child is %d, and the right child is %d
    ",i,tree[i].fa,tree[i].l,tree[i].r);
        }
        return 0;
    }
    View Code

    E.牛牛的随机数 

    https://ac.nowcoder.com/acm/contest/3004/E

    F.牛牛的Link Power I

    利用前缀和的思想,每右移动一次,在当前的点插入一个1的贡献增加幅度就会增加前面的点数。

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <queue>
    #include <set>
    #include <map>
    #include <stack>
    
    using namespace std;
    #define scd(a) scanf("%d",&a)
    #define scdd(a,b) scanf("%d%d",&a,&b)
    #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
    #define scl(a) scanf("%lld",&a)
    #define scll(a,b) scanf("%lld%lld",&a,&b)
    #define prl(a) printf("%lld
    ",a)
    #define prd(a) printf("%d
    ",a)
    #define prf(a) printf("%lf
    ",a)
    #define ptd(a) printf("%d ",a)
    #define scf(a) scanf("%lf",&a)
    #define scff(a,b) scanf("%lf%lf",&a,&b)
    #define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
    #define rint register int
    #define mem(a) memset(a,0,sizeof(a))
    #define rush() int T;scd(T);while(T--)
    #define lc(i) (i<<1)
    #define rc(i) (i<<1|1)
    #define mp make_pair
    typedef long long ll;
    typedef double db;
    inline int read() {char c=getchar();int x=0,f=1;while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}return x*f;}
    const int maxn = 1e5 + 10;
    const ll mod = 1e9 + 7;
    char s[maxn];
    int main() {
        int n = read();
        cin >> s;
        bool st = false;
        ll add = 0;
        ll pre = 0, ans = 0;
        for (int i = 0; i < n; ++i) {
            if (!st) {
                if (s[i]=='1') {
                    st = true;
                    pre = 1;
                    add = 0;
                }
            }
            else {
                add = (add + pre) % mod;
                if (s[i]=='1') {
                    ans = (ans + add) % mod;
                    pre++;
                    pre %= mod;
                }
            }
        }
        prl(ans);
        return 0;
    }
    View Code

    G牛牛的Link Power 2

    写的时间久的好处是,只用了一个函数就解决了战斗。

    lsum 和 rsum 是上一题的思想,在l处或者是r处插入一个1的贡献,单点更新以后,区间合并的贡献当然包含了左右两边的1互相(瞎搞)的贡献,然后左边的点想着跑到右边瞎搞,右边的点想着去跟左边的点私会,左边每一个点可以跟右边的每一个点做出贡献,右边也是,所以对一个【(L,mid),(mid+1,R)】这种合并呢,先计算所有左边的点跑到mid的贡献,再计算所有右边的点爬到mid+1的点的贡献,这个时候他们还有一个分界线没有越过,要么是左边越过要么是右边越过,但是,就已经相当于是两个1相邻的情况了,毕竟只差一步左右两边就可以瞎搞了。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <stack>
    #include <queue>
    #include <vector>
    #include <set>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define scd(a) scanf("%d",&a)
    #define scdd(a,b) scanf("%d%d",&a,&b)
    #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
    #define scl(a) scanf("%lld",&a)
    #define scll(a,b) scanf("%lld%lld",&a,&b)
    #define prl(a) printf("%lld
    ",a)
    #define prd(a) printf("%d
    ",a)
    #define prf(a) printf("%lf
    ",a)
    #define ptd(a) printf("%d ",a)
    #define scf(a) scanf("%lf",&a)
    #define scff(a,b) scanf("%lf%lf",&a,&b)
    #define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
    #define rint register int
    #define mem(a) memset(a,0,sizeof(a))
    #define rush() int T;scd(T);while(T--)
    #define lc(i) (i<<1)
    #define rc(i) (i<<1|1)
    #define mp make_pair
    #define scs(x) scanf("%s", x)
    const int maxn = 1e5+2;
    const int MOD = 1e9+7;
    const double Pi = acos(-1.0);
    const double eps = 1e-6;
    #define mid ((l+r)>>1)
    #define lson rt<<1, l, mid
    #define rson rt<<1|1, mid+1, r
    char s[maxn];
    struct node{
        int left, right;
        ll num;
        ll ans;
        ll lsum, rsum;
    }tree[maxn<<2];
    void update(int rt, int l, int r, int p) {
        tree[rt].left = l;
        tree[rt].right = r;
        if (l == r) {
            tree[rt].num = s[l]-'0';
            tree[rt].ans = 0;
            tree[rt].lsum = tree[rt].rsum = 0;
            return;
        }
        if (p <= mid) {
            update(lc(rt),l,mid,p);
        }
        else {
            update(rc(rt),mid+1,r,p);
        }
        tree[rt].num = tree[rt<<1].num + tree[rt<<1|1].num;
        tree[rt].lsum = ( tree[rt<<1].lsum + tree[rt<<1|1].lsum + tree[rt<<1|1].num*(tree[rt<<1|1].left-tree[rt<<1].left) )%MOD;
        tree[rt].rsum = ( tree[rt<<1].rsum + tree[rt<<1|1].rsum + tree[rt<<1].num*(tree[rt<<1|1].right-tree[rt<<1].right) )%MOD;
        tree[rt].ans = (tree[lc(rt)].ans + tree[rc(rt)].ans)%MOD + ((tree[lc(rt)].rsum + tree[lc(rt)].num)%MOD * (tree[rc(rt)].num)%MOD + tree[rc(rt)].lsum * (tree[lc(rt)].num)%MOD)%MOD;
        tree[rt].ans %= MOD;
    }
    int main()
    {
        int n;
        scd(n);
        scs(s+1);
        set<int> sat;
        for (int i = 1; i <= n; ++i) {
            update(1,1,n,i);
        }
    //    for (int i = 1; i<=n<<2;++i)printf("i = %d ans=%d num=%d
    ", i, tree[i].ans,tree[i].num);
        printf("%lld
    ",tree[1].ans);
        int m;scd(m);
        for (int i = 0; i<m; ++i) {
            int t,ps;scdd(t,ps);
            if (t==1){
                if (s[ps]=='0'){
                    s[ps]='1';
                }
            }else{
                if(s[ps]=='1'){
                    s[ps]='0';
                }
            }
            update(1,1,n,ps);
            printf("%lld
    ",tree[1].ans);
        }
        return 0;
    }
    /*
    10
    0101111001
    */
    View Code

    H牛牛的k合因子数

    埃筛多加了点东西,在筛的时候对于x是素数的情况,x的倍数的合因子包含了本身,x不是素数即为合数的时候,x是x的倍数的合因子

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <queue>
    #include <set>
    #include <map>
    #include <stack>
    
    using namespace std;
    #define scd(a) scanf("%d",&a)
    #define scdd(a,b) scanf("%d%d",&a,&b)
    #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
    #define scl(a) scanf("%lld",&a)
    #define scll(a,b) scanf("%lld%lld",&a,&b)
    #define prl(a) printf("%lld
    ",a)
    #define prd(a) printf("%d
    ",a)
    #define prf(a) printf("%lf
    ",a)
    #define ptd(a) printf("%d ",a)
    #define scf(a) scanf("%lf",&a)
    #define scff(a,b) scanf("%lf%lf",&a,&b)
    #define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
    #define rint register int
    #define mem(a) memset(a,0,sizeof(a))
    #define rush() int T;scd(T);while(T--)
    #define lc(i) (i<<1)
    #define rc(i) (i<<1|1)
    #define mp make_pair
    typedef long long ll;
    typedef double db;
    inline int read() {char c=getchar();int x=0,f=1;while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}return x*f;}
    const int maxn = 1e5 + 10;
    const int mod = 1e9 + 7;
    int isprime[maxn];
    int cnt[maxn];
    int main() {
        int n = read(),m = read();
        for (int i = 2; i <= n; ++i) isprime[i] = 1;
        for (int i = 2; i <= n; ++i) {
            if (isprime[i] == 1) {
                for (int j = i + i; j <= n; j+=i) {
                    isprime[j] = 0;
                    cnt[j] = max(cnt[j], 1);
                }
            }
            else {
                for (int j = i + i; j <= n; j+=i) {
                    cnt[j]++;
                }
            }
        }
        map<int,int>ans;
        for (int i = 2; i <= n; ++i) {
            if (ans.count(cnt[i]) == 0) {
                ans[cnt[i]] = 1;
            }
            else
                ans[cnt[i]]++;
        }
        while (m--) {
            int q = read();
            if (ans.count(q) == 0) prd(0);
            else prd(ans[q]);
        }
        return 0;
    }
    View Code

    I牛牛的汉诺塔

    60这个东西,显然是为了不爆掉,递归找规律

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <queue>
    #include <set>
    #include <map>
    #include <stack>
    
    using namespace std;
    #define scd(a) scanf("%d",&a)
    #define scdd(a,b) scanf("%d%d",&a,&b)
    #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
    #define scl(a) scanf("%lld",&a)
    #define scll(a,b) scanf("%lld%lld",&a,&b)
    #define prl(a) printf("%lld
    ",a)
    #define prd(a) printf("%d
    ",a)
    #define prf(a) printf("%lf
    ",a)
    #define ptd(a) printf("%d ",a)
    #define scf(a) scanf("%lf",&a)
    #define scff(a,b) scanf("%lf%lf",&a,&b)
    #define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
    #define rint register int
    #define mem(a) memset(a,0,sizeof(a))
    #define rush() int T;scd(T);while(T--)
    #define lc(i) (i<<1)
    #define rc(i) (i<<1|1)
    #define mp make_pair
    typedef long long ll;
    typedef double db;
    inline int read() {char c=getchar();int x=0,f=1;while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}return x*f;}
    const int maxn = 100 + 10;
    const int mod = 1e9 + 7;
    ll cnt[maxn][10][10];
    int nn;
    void Hanoi(int n,int a,int b,int c)
    {
        if (n==1) {
            cnt[nn][a][c]++;
        }
        else{
            Hanoi(n-1,a,c,b);
            cnt[nn][a][c]++;
            Hanoi(n-1,b,a,c);
        }
    }
    ll dp[maxn][10];
    int main() {
    //    while (1){
    //    }
    //    while (1){
            int n = read();
            mem(dp);
            dp[1][2] = 1;
            dp[1][7] = 1;
            for (int i = 2; i<=n; ++i) {
                dp[i][7] = dp[i-1][7] * 2 + 1;
                dp[i][1]=dp[i][4]=dp[i-1][2]+dp[i-1][3];
                dp[i][2]=dp[i-1][1]*2+1;
                dp[i][5]=dp[i-1][3]*2;
                dp[i][3]=dp[i][6]=(dp[i][7]-dp[i][1]-dp[i][2]-dp[i][4]-dp[i][5])/2;
            }
            printf("A->B:%lld
    ",dp[n][1]);
            printf("A->C:%lld
    ",dp[n][2]);
            printf("B->A:%lld
    ",dp[n][3]);
            printf("B->C:%lld
    ",dp[n][4]);
            printf("C->A:%lld
    ",dp[n][5]);
            printf("C->B:%lld
    ",dp[n][6]);
            printf("SUM:%lld
    ",dp[n][7]);
    //        Hanoi(nn=n,1,2,3);
    //        int sum = 0;
    //        for (int i=1;i<=3;++i){
    //            for (int j=1;j<=3;++j){
    //                if(i==j)continue;
    //                sum += cnt[nn][i][j];
    //                printf("%c->%c:%lld
    ",i+'A'-1,j+'A'-1,cnt[nn][i][j]);
    //            }
    //        }
    //        prd(sum);
    //    }
        return 0;
    }
    View Code

    J牛牛的宝可梦

    200个点的最短路提示了到floyd为止都是非常自然的想法,抓精灵这个事情要看时间(RP)和攻击力(面板),在某一个地点抓到精灵的最优解一种做法是要对上一个地点遍历,然后我们按照时间找到时间最晚的解,把它当成是在这个地点的最优解,因为随着精灵的不断出现每一个地点的最优解都是不断更新的,所以二分查找到上一个地点最晚的时间更新即可。还有一种做法就是啥都不做,在一个地方抓到了一只精灵以后,在别的地方瞎跑抓精灵说不定比不上在这个地点等到一只满攻精灵,然后再跑过来的收获大。

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define mp make_pair
    const int maxn = 200+20;
    const int inf = 0x3f3f3f3f;
    typedef long long ll;
    ll dist[maxn][maxn];
    struct node {
        int t,id;
        int val;
    } p[100010];
    bool cmp(node& a,node& b) {
        return a.t<b.t;
    }
    vector<pair<int,int> >dp[maxn];
    ll f[100010];
    int main() {
        int n,m;
        scanf("%d%d",&n,&m);
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j)
                dist[i][j] = inf;
            dist[i][i]=0;
        }
        for (int i = 0; i < m; ++i) {
            int u, v;
            scanf("%d%d",&u,&v);
            dist[u][v] = dist[v][u] = min(dist[u][v], 1ll);
        }
        for (int k = 1; k <= n; ++k) {
            for (int i = 1; i <= n; ++i) {
                for (int j = 1; j <= n; ++j) {
                    dist[j][i] = dist[i][j] = min(dist[i][j],dist[i][k]+dist[k][j]);
                }
            }
        }
        int k;
        scanf("%d",&k);
        for (int i = 1; i <= k; ++i) {
            scanf("%d%d%d",&p[i].t,&p[i].id,&p[i].val);
        }
        p[0].t=p[0].val=0;
        p[0].id=1;
        sort(p+1,p+1+k,cmp);
        ll ans = 0;
        dp[1].push_back(mp(0,0));
        for (int i = 1; i <= k; ++i)
            f[i] = -inf;
        f[0]=0;
        for (int i = 1; i <= k; ++i) {
            for (int j = 1; j <= n; ++j) {
                if(dp[j].empty()) continue;
                int dis=dist[j][p[i].id];
                if (dis!=inf) {
                    int id = upper_bound(dp[j].begin(), dp[j].end(), mp(p[i].t-dis, inf))-dp[j].begin()-1;
                    if(id >= 0) {
                        f[i]=max(f[i],f[dp[j][id].second]+p[i].val);
                    }
                }
            }
            if (dp[p[i].id].empty()==false) {
                f[i]=max(f[i], f[dp[p[i].id].back().second]);
            }
            dp[p[i].id].push_back(mp(p[i].t, i));
            ans=max(ans,f[i]);
        }
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

    另外再附加一种好像是标称,但是还是不怎么懂i-j<=200这个条件,如果说是当前这个精灵的出现的最优解肯定是由200个地点某一个地点过来的,那么最优解为什么是前200个状态来的呢。。。已经测试过把精灵的出现时间p[i].t - p[j].t <= 200,结果:wa

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
     
    const int maxn = 200+20;
    const int inf = 0x3f3f3f3f;
    typedef long long ll;
    ll dist[maxn][maxn];
    struct node {
        int t,id;
        ll val;
    }p[100010];
    bool cmp(node& a,node& b){
        return a.t<b.t;
    }
    ll dp[100010];
    int main() {
        int n,m;
        scanf("%d%d",&n,&m);
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j)
                dist[i][j] = inf;
            dist[i][i]=0;
        }
        for (int i = 0; i < m; ++i) {
            int u, v;scanf("%d%d",&u,&v);
            dist[u][v] = dist[v][u] = min(dist[u][v], 1ll);
        }
        for (int k = 1; k <= n; ++k) {
            for (int i = 1; i <= n; ++i) {
                for (int j = 1; j <= n; ++j) {
                    dist[j][i] = dist[i][j] = min(dist[i][j],dist[i][k]+dist[k][j]);
                }
            }
        }
        int k;scanf("%d",&k);
        for (int i = 1; i <= k; ++i) {
            scanf("%d%d%lld",&p[i].t,&p[i].id,&p[i].val);
        }
        p[0].t=p[0].val=0;
        p[0].id=1;
        sort(p+1,p+1+k,cmp);
        ll ans = 0;
        for (int i = 1; i <= k; ++i) dp[i]=-1;
        dp[0]=0;
        for (int i = 0; i <= k; ++i) {
            for (int j = i-1; ~j&&i-j<=200; --j) {
                if (p[i].t-p[j].t>=dist[p[i].id][p[j].id]&&~dp[j])
                    dp[i]=max(dp[i],dp[j]+p[i].val);
            }
            ans=max(ans,dp[i]);
        }
        printf("%lld
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    Spark RDD操作(1)
    scala学习笔记(8): 列表的map,flatMap,zip和reduce
    (转)hadoop基本操作命令
    Mac下配置环境变量
    Spark快速入门(1)
    urllib2 request 模拟伪装浏览器
    linux下面Zookeeper的单机模式(standalone)
    linux redis安装
    python OCR 图形识别
    mysql 、慢查询、到底如何玩
  • 原文地址:https://www.cnblogs.com/Urchin-C/p/12287604.html
Copyright © 2020-2023  润新知