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\n",a)
#define prd(a) printf("%d\n",a)
#define prf(a) printf("%lf\n",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\n",a)
#define prd(a) printf("%d\n",a)
#define prf(a) printf("%lf\n",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\n",a)
#define prd(a) printf("%d\n",a)
#define prf(a) printf("%lf\n",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\n",a)
#define prd(a) printf("%d\n",a)
#define prf(a) printf("%lf\n",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\n",sz);
    printf("Node %d is the root node of the tree\n", 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\n",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\n",a)
#define prd(a) printf("%d\n",a)
#define prf(a) printf("%lf\n",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\n",a)
#define prd(a) printf("%d\n",a)
#define prf(a) printf("%lf\n",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\n", i, tree[i].ans,tree[i].num);
    printf("%lld\n",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\n",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\n",a)
#define prd(a) printf("%d\n",a)
#define prf(a) printf("%lf\n",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\n",a)
#define prd(a) printf("%d\n",a)
#define prf(a) printf("%lf\n",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\n",dp[n][1]);
        printf("A->C:%lld\n",dp[n][2]);
        printf("B->A:%lld\n",dp[n][3]);
        printf("B->C:%lld\n",dp[n][4]);
        printf("C->A:%lld\n",dp[n][5]);
        printf("C->B:%lld\n",dp[n][6]);
        printf("SUM:%lld\n",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\n",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\n",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\n",ans);
    return 0;
}
View Code
posted @ 2020-02-09 16:42  czwccc  阅读(136)  评论(0编辑  收藏  举报