本校大佬阿珂了的时候我还在模拟线段树,虽然还是在最后时间内卡进去了,基础不好呀,说明还是要不好高骛远了,见到数论就不想动不晓得是是自以为跟哪个学长学的,真想开口说自己也是一名数论选手。
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;
}
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;
}
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;
}
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;
}
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;
}
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
*/
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;
}
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;
}
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;
}
另外再附加一种好像是标称,但是还是不怎么懂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;
}
来源:https://www.cnblogs.com/Urchin-C/p/12287604.html
