A
题意 求最大M子段和
其实就是 dp[i][j] 代表以i结尾(i必须取) 已经有j个子段的最大值
那么dp[i][j] 只能通过 dp[i-1][j] 和 dp[i-1][j-1] 过来
dp[i]代表到i位置分的段数
滚动数组优化一维后发现其实和BZOJ 1270有异曲同工之妙
记录一个最大值 然后最大值作为上一个循环的最大值传过来进行直接传递
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=1e6+5;
int n,m,arr[N];
//int f[N][N];
int dp[N],maxn[N];
int main(){
while(scanf("%d%d",&m,&n)==2)
{
for(int i = 1;i<=n;++i) scanf("%d",&arr[i]);
memset(dp,0,sizeof(dp));
memset(maxn,0,sizeof(maxn));
int nowans = 0;
for(int i = 1;i<=m;++i)
{
nowans = -1e9;
for(int j = i ;j<=n;++j)
{
dp[j] = max(dp[j-1],maxn[j-1]) + arr[j];
maxn[j-1] = nowans;
nowans = max(dp[j],nowans);
}
}
printf("%d\n",nowans);
}
return 0;
}
B
求至少出现n/2的次数
不知道为啥在dp专题里 我直接sort过的
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)
typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 1000025;
int arr[MAX_N];
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int n;
while(scanf("%d",&n)==1)
{
for(int i = 1;i<=n;++i)
scanf("%d",&arr[i]);
sort(arr+1,arr+1+n);
printf("%d\n",arr[n/2+1]);
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
C
猴子摆塔
做法就是把每一个东西都衍生出5个新东西
然后按照 长从大到小 宽从大到小 类似Lis 的求法去求出答案即可
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)
typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 200;
int dp[MAX_N];
struct node
{
int x,y,z;
bool operator<(const node other) const
{
if(x==other.x)
{
if(y==other.y)
{
return z > other.z;
}
return y >other.y;
}
return x > other.x;
}
}arr[MAX_N];
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int n,ans,Case = 0;
while(scanf("%d",&n)==1)
{
ans = 0;
if(!n) break;
for(int i = 1;i<=n;++i)
{
scanf("%d%d%d",&arr[i].x,&arr[i].y,&arr[i].z);
arr[n*1+i].x = arr[i].x,arr[n*1+i].y = arr[i].z,arr[n*1+i].z = arr[i].y;
arr[n*2+i].x = arr[i].y,arr[n*2+i].y = arr[i].z,arr[n*2+i].z = arr[i].x;
arr[n*3+i].x = arr[i].y,arr[n*3+i].y = arr[i].x,arr[n*3+i].z = arr[i].z;
arr[n*4+i].x = arr[i].z,arr[n*4+i].y = arr[i].x,arr[n*4+i].z = arr[i].y;
arr[n*5+i].x = arr[i].z,arr[n*5+i].y = arr[i].y,arr[n*5+i].z = arr[i].x;
}
sort(arr+1,arr+1+6*n);
for(int i = 1;i<=6*n;++i) dp[i] = arr[i].z;
for(int i = 1;i<=6*n;++i)
{
for(int j = 1;j<i;++j)
{
if(arr[i].x<arr[j].x&&arr[i].y<arr[j].y)
{
dp[i] = max(dp[i],dp[j]+arr[i].z);
}
}
}
for(int i = 1;i<=6*n;++i)
ans = max(ans,dp[i]);
printf("Case %d: maximum height = %d\n",++Case,ans);
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
D
做作业 发现作业只有15个 很容易想到状态压缩
那么我们枚举几个作业的时候 就要找这么多作业包含的那一个作业
然后枚举去掉他和加上他的情况 来进行dp
主要是位运算操作都在代码里面
然后用pre 数组输出答案
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)
typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 200;
char str[16][MAX_N];
struct node
{
int l,r;
}arr[16];
int pre[65545],dp[65545],tm[65545];
void write(int x)
{
if(x==0) return;
write(x^(1<<pre[x]));
printf("%s\n",str[pre[x]]);
}
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int n,t;scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i = 0;i<n;++i) scanf("%s%d%d",str[i],&arr[i].l,&arr[i].r);
memset(dp,0x3f,sizeof(dp));
dp[0] = 0;
for(int i = 1;i<(1<<n);++i)
{
for(int j = n-1;j>=0;--j)
{
int tt = 1<<j;
if(!(i&tt)) continue;
tt = i^tt;
int tmp = tm[tt] + arr[j].r - arr[j].l;
tmp = tmp<0?0:tmp;
if(dp[i]>dp[tt]+tmp)
{
dp[i] = dp[tt]+tmp;
tm[i] = tm[tt] + arr[j].r;
pre[i] = j;
}
}
}
printf("%d\n",dp[(1<<n)-1]);
write((1<<n)-1);
memset(pre,0,sizeof(pre));
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
E
类似Lis 只不过状态转移方程要统计的是每个点的权值和
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)
typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 1025;
int arr[MAX_N];
ll dp[MAX_N];
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int n;
while(scanf("%d",&n)==1)
{
ll ans = 0;
if(!n) break;
for(int i = 1;i<=n;++i)
scanf("%d",&arr[i]),dp[i] = arr[i];
for(int i = 1;i<=n;++i)
for(int j = 1;j<i;++j)
{
if(arr[i]>arr[j])
{
dp[i] = max(dp[i],dp[j]+arr[i]);
}
}
for(int i = 1;i<=n;++i)
ans = max(ans,dp[i]);
printf("%lld\n",ans);
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
F
题意 给你开始重量和结束重量 问你装最少的钱使得重量加上开始重量等于结束重量
完全背包水题
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)
typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 505;
int val[MAX_N],v[MAX_N];
long long dp[10025];
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int t,E,F,n;scanf("%d",&t);
while(t--)
{
scanf("%d%d",&E,&F);
scanf("%d",&n);for(int i = 1;i<=n;++i) scanf("%d%d",&val[i],&v[i]);
memset(dp,0x7f7f7f7f,sizeof(dp));
ll tmp = dp[F];
dp[0] = 0;F -= E;
for(int i = 1;i<=n;++i)
{
for(int j = v[i];j<=F;++j)
{
dp[j] = min(dp[j],dp[j-v[i]]+val[i]);
}
}
if(dp[F]==tmp) printf("This is impossible.\n");
else printf("The minimum amount of money in the piggy-bank is %lld.\n",dp[F]);
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
G
中文题面
dp[i][j]代表第 i 秒 第 j 坐标的地方能接的方案数
因为 0 到 11 所以我把坐标都加了1
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)
typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
int dp[100025][15],arr[100025][15];
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int n,x,tm,ans,maxx;
while(scanf("%d",&n)==1)
{
ans = 0;
if(!n) break;
memset(arr,0,sizeof(arr));
memset(dp,0x80,sizeof(dp));
dp[0][6] = 0;
for(int i = 1;i<=n;++i)
{
scanf("%d%d",&x,&tm),x++;
arr[tm][x]++;
}
for(int i = 1;i<100000;i++)
{
for(int j = 1;j<=11;j++)
{
if(j==1) dp[i][j] = max(dp[i-1][j],dp[i-1][j+1]) + arr[i][j];
else if(j==11) dp[i][j] = max(dp[i-1][j],dp[i-1][j-1]) + arr[i][j];
else dp[i][j] = max(dp[i-1][j],max(dp[i-1][j-1],dp[i-1][j+1])) + arr[i][j];
ans = max(dp[i][j],ans);
}
}
printf("%d\n",ans);
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
H
买票 容易想到dp[i]代表第i个人已经买完票的花费
那么我们顺推过去 dp[i] = max(dp[i-1]+arr[i],dp[i-2]+b[i])
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)
typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 2025;
int arr[MAX_N],dp[MAX_N],b[MAX_N];
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int t;scanf("%d",&t);
while(t--)
{
int n;scanf("%d",&n);
for(int i = 1;i<=n;++i) scanf("%d",&arr[i]);
for(int i = 2;i<=n;++i) scanf("%d",&b[i]);b[1] = 0x3f3f3f3f;
memset(dp,0x3f,sizeof(dp));
dp[0] = 0;
for(int i = 1;i<=n;++i)
{
if(i==1) dp[i] = dp[i-1]+arr[i];
else dp[i] = min(dp[i-1]+arr[i],dp[i-2]+b[i]);
}
int tmp__ = dp[n]%60,tmp_ = dp[n]/60%60,tmp = dp[n]/3600;
printf("%02d:%02d:%02d ",tmp+8,tmp_,tmp__);
if(tmp+8>=12) printf("pm\n");
else printf("am\n");
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
I
求的是最长上升子序列长度 一开始忘记从2开始WA了一发
这是nlogn的实现方法 原理就是我们的这个Lis 如果相同位置 我要值最小的
这样后面才有可能塞更多东西
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)
typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 30025;
int arr[MAX_N],ans[MAX_N];
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int n;
while(scanf("%d",&n)==1)
{
int len = 1;
for(int i = 1;i<=n;++i)
scanf("%d",&arr[i]);
ans[len] = arr[1];
for(int i = 2;i<=n;++i)
if(arr[i]>ans[len]) ans[++len] = arr[i];
else *(lower_bound(ans+1,ans+1+len,arr[i])) = arr[i];
printf("%d\n",len);
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
J
题意 求第一个序列递增 第二个序列递降的最长长度以及序列
我们只要按照第一个个序列递增 第二个序列递减排序 用求Lis的方法求最长长度
并且用vector记录取的序列
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)
typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 1025;
int dp[MAX_N];
vector<int > vt[MAX_N];
struct node
{
int l,r,id;
bool operator<(const node other) const
{
if(l==other.l) return r > other.r;
return l < other.l;
}
}arr[MAX_N];
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int ans = 1,xb = 1,n = 1;
while(scanf("%d%d",&arr[n].l,&arr[n].r)==2)
{
arr[n].id = n;
n++;
}
n--;
sort(arr+1,arr+1+n);
for(int i = 1;i<=n;++i) dp[i] = 1,vt[i].push_back(arr[i].id);
for(int i = 1;i<=n;++i)
{
for(int j = 1;j<i;++j)
{
if(arr[i].l>arr[j].l&&arr[i].r<arr[j].r)
{
if(dp[i]<dp[j]+1)
{
dp[i] = dp[j]+1;
vector<int> vt_;
swap(vt[i],vt_);
int sz = vt[j].size();
for(int k = 0;k<sz;++k) vt[i].push_back(vt[j][k]);
vt[i].push_back(arr[i].id);
if(ans<dp[i])
{
ans = dp[i];
xb = i;
}
}
}
}
}
printf("%d\n",ans);
for(int i = 0;i<vt[xb].size();i++)
printf("%d\n",vt[xb][i]);
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
L
LCS水题
dp[i][j] 代表 第一个串的 i 长度 和第二个串的 j 长度的最长公共子序列长度
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)
typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 10025;
char str[MAX_N],str_[MAX_N];
int dp[MAX_N][MAX_N];
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
while(scanf("%s%s",str+1,str_+1)==2)
{
int len = strlen(str+1),len_ = strlen(str_+1);
for(int i = 1;i<=len;++i)
for(int j = 1;j<=len_;++j)
dp[i][j] = 0;
for(int i = 1;i<=len;++i)
for(int j = 1;j<=len_;++j)
if(str[i]==str_[j]) dp[i][j] = dp[i-1][j-1] + 1;
else dp[i][j] = max(dp[i][j-1],dp[i-1][j]);
printf("%d\n",dp[len][len_]);
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
M
好久以前自己写出来的 不优雅 现在也忘记dp意义了没看这题
/*
POJ 1661
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
//#define dbg(x) cout<<#x<<" = "<< (x)<< endl
using namespace std;
const int MAX_N = 20024;
struct node
{
int l;
int r;
int h;
bool operator < (const node other) const
{
if(h==other.h&&l==other.l)
return r<other.r;
if(h==other.h)
return l<other.l;
return h<other.h;
}
} arr[MAX_N];
long long dp[MAX_N][2];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(dp,0x3f,sizeof(dp));
int n,x,y,H;
scanf("%d%d%d%d",&n,&x,&y,&H);
for(int i = 1; i<=n; ++i)
scanf("%d%d%d",&arr[i].l,&arr[i].r,&arr[i].h);
sort(arr+1,arr+1+n);
arr[0].l = -20022;
arr[0].r = 20022;
arr[0].h = 0;
arr[n+1].l = x;
arr[n+1].r = x;
arr[n+1].h = y;
dp[n+1][1] = 0;
dp[n+1][0] = 0;
for(int i = n; i>=0; i--)
{
if(i==0)
{
for(int j = 1; j<=n+1; j++)
{
int flag = 0,flag_l = 0,flag_r=0;
if(arr[j].h-arr[i].h>H)
break;
if(arr[j].l<=arr[i].r&&arr[j].l>=arr[i].l&&arr[j].r>=arr[i].l&&arr[j].r<=arr[i].r)
{
if(j!=i+1)
{
for(int k = i+1; k<j; k++)
{
if(arr[k].l<arr[j].l&&arr[k].r>arr[j].l)
{
flag_l = 1;
break;
}
}
for(int k = i+1; k<j; k++)
{
if(arr[k].l<arr[j].r&&arr[k].r>arr[j].r)
{
flag_r = 1;
break;
}
}
}
if(flag_l&&flag_r)
continue;
else if(flag_l)
{
dp[0][0] = min(dp[0][0],dp[j][1]+arr[j].h);
}
else if(flag_r)
{
dp[0][0] = min(dp[0][0],dp[j][0]+arr[j].h);
}
else
dp[0][0] = min(dp[0][0],min(dp[j][0],dp[j][1])+arr[j].h);
}
else if(arr[j].l<=arr[i].r&&arr[j].l>=arr[i].l)
{
if(j!=i+1)
{
for(int k = i+1; k<j; k++)
{
if(arr[k].r>arr[j].l&&arr[k].l<arr[j].l)
{
flag = 1;
break;
}
}
}
if(flag)
continue;
dp[0][0] = min(dp[0][0],dp[j][0]+arr[j].h);
}
else if(arr[j].r>=arr[i].l&&arr[j].r<=arr[i].r)
{
if(j!=i+1)
{
for(int k = i+1; k<j; k++)
{
if(arr[k].r>arr[j].r&&arr[k].l<arr[j].r)
{
flag = 1;
break;
}
}
}
if(flag)
continue;
dp[0][0] = min(dp[0][0],dp[j][1]+arr[j].h);
}
else
continue;
}
}
else
{
for(int j = i+1; j<=n+1; j++)
{
int flag_l = 0,flag_r=0,flag = 0;
if(arr[j].h-arr[i].h>H)
break;
if(arr[j].l<=arr[i].r&&arr[j].l>=arr[i].l&&arr[j].r<=arr[i].r)
{
if(j!=i+1)
{
for(int k = i+1; k<j; k++)
{
if(arr[k].l<arr[j].l&&arr[k].r>arr[j].l)
{
flag_l = 1;
break;
}
}
for(int k = i+1; k<j; k++)
{
if(arr[k].l<arr[j].r&&arr[k].r>arr[j].r)
{
flag_r = 1;
break;
}
}
}
if(flag_l&&flag_r)
continue;
else if(flag_l)
{
dp[i][0] = min(dp[i][0],dp[j][1]+arr[j].r-arr[i].l+arr[j].h-arr[i].h);
dp[i][1] = min(dp[i][1],dp[j][1]+arr[i].r-arr[j].r+arr[j].h-arr[i].h);
}
else if(flag_r)
{
dp[i][0] = min(dp[i][0],dp[j][0]+arr[j].l-arr[i].l+arr[j].h-arr[i].h);
dp[i][1] = min(dp[i][1],dp[j][0]+arr[i].r-arr[j].l+arr[j].h-arr[i].h);
}
else
{
dp[i][0] = min(dp[i][0],min(dp[j][0]+arr[j].l-arr[i].l+arr[j].h-arr[i].h,dp[j][1]+arr[j].r-arr[i].l+arr[j].h-arr[i].h));
dp[i][1] = min(dp[i][1],min(dp[j][0]+arr[i].r-arr[j].l+arr[j].h-arr[i].h,dp[j][1]+arr[i].r-arr[j].r+arr[j].h-arr[i].h));
}
}
else if(arr[j].r>=arr[i].l&&arr[j].r<=arr[i].r)
{
if(j!=i+1)
{
for(int k = i+1; k<j; k++)
{
if(arr[k].r>arr[j].r&&arr[k].l<arr[j].r)
{
flag = 1;
break;
}
}
}
if(flag)
continue;
dp[i][0] = min(dp[i][0],dp[j][1]+arr[j].r-arr[i].l+arr[j].h-arr[i].h);
dp[i][1] = min(dp[i][1],dp[j][1]+arr[i].r-arr[j].r+arr[j].h-arr[i].h);
}
else if(arr[j].l<=arr[i].r&&arr[j].l>=arr[i].l)
{
if(j!=i+1)
{
for(int k = i+1; k<j; k++)
{
if(arr[k].r>arr[j].l&&arr[k].l<arr[j].l)
{
flag = 1;
break;
}
}
}
if(flag)
continue;
dp[i][0] = min(dp[i][0],dp[j][0]+arr[j].l-arr[i].l+arr[j].h-arr[i].h);
dp[i][1] = min(dp[i][1],dp[j][0]+arr[i].r-arr[j].l+arr[j].h-arr[i].h);
}
else
continue;
}
}
}
printf("%lld\n",min(min(dp[1][0],dp[1][1])+arr[1].h,dp[0][0]));
}
return 0;
}
N
最水的LIS
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)
typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 1025;
int arr[MAX_N],ans[MAX_N];
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int len = 1,n;scanf("%d",&n);
for(int i = 1;i<=n;++i) scanf("%d",&arr[i]);
ans[len] = arr[1];
for(int i = 2;i<=n;++i)
if(arr[i]>ans[len]) ans[++len] = arr[i];
else *(lower_bound(ans+1,ans+1+len,arr[i])) = arr[i];
printf("%d\n",len);
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
O
敦敦敦讲过的区间dp
我们定义dp[l][r]就是 l 到 r 按照此规则形成的答案
那么我们知道 dp[l][r] 只能从 dp[l+1][r] 和 dp[l][r-1] 形成
那么我们根据这个性质去转移dp就可以了
然后对于每个串 你是知道他加串的那个顺序的
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)
typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 2025;
int arr[MAX_N],dp[MAX_N][MAX_N];
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int n,ans = 0;scanf("%d",&n);
for(int i = 1;i<=n;++i) scanf("%d",&arr[i]),dp[i][i] = arr[i];
arr[0] = 0,arr[n+1] =0;
for(int i = n;i>=1;--i)
{
for(int j = i;j<=n;++j)
{
dp[i][j] = max(dp[i+1][j]+(n+i-j)*arr[i],dp[i][j-1]+(n+i-j)*arr[j]);
}
}
printf("%d\n",dp[1][n]);
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
P
搜索的时候采用记忆化 然后直接返回答案即可
/*
hdoj 1078
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
using namespace std;
const int MAX_N = 124;
int k,n;
long long dp[MAX_N][MAX_N],arr[MAX_N][MAX_N];
int dir[4][2] = {1,0,-1,0,0,-1,0,1};
long long dfs(int x,int y){
long long ans = 0;
if(!dp[x][y]){
for(int i = 1;i<=k;i++){
for(int j = 0;j<4;j++){
int xx = x + dir[j][0]*i;
int yy = y + dir[j][1]*i;
if(xx<1||xx>n||yy<1||yy>n) continue;
if(arr[xx][yy]>arr[x][y]) ans=max(ans,dfs(xx,yy));
}
}
dp[x][y] = ans;
}
return dp[x][y]+arr[x][y];
}
int main(){
while(scanf("%d%d",&n,&k)){
memset(dp,0,sizeof(dp));
if(n==-1&&k==-1) break;
for(int i = 1;i<=n;i++)
for(int j = 1;j<=n;j++)
scanf("%lld",&arr[i][j]);
printf("%lld\n",dfs(1,1));
}
return 0;
}
Q题的哈希是跟学长学的 十分的妙
/*
hdoj 2859
*/
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
typedef unsigned long long ull;
const int maxn = 1e3+5;
ull hash_1[maxn][maxn],hash_2[maxn][maxn],xp[maxn];
char str[maxn][maxn];
void init()
{
xp[0]=1;
for(int i=1;i<maxn;i++)
xp[i]=xp[i-1]*13331;//这里13331玄学数字,大概可以随意换
return ;
}
void make_hash(int n)//处理出str的hash值
{
for(int i=0;i<n;i++)
{
hash_1[i][n]=0;
for(int j=n-1;j>=0;j--)
{
hash_1[i][j]=hash_1[i][j+1]*13331+(str[i][j]-'A')+1;
}
}
for(int i=0;i<n;i++)
{
hash_2[i][n]=0;
for(int j=n-1;j>=0;j--)
{
hash_2[i][j]=hash_2[i][j+1]*13331+str[j][i]-'A'+1;
}
}
return ;
}
ull Get_hash1(int x,int i,int L)//得到起点为i,长度为L的子串的hash值
{
return hash_1[x][i]-hash_1[x][i+L]*xp[L];
}
ull Get_hash2(int x,int i,int L)//得到起点为i,长度为L的子串的hash值
{
return hash_2[x][i]-hash_2[x][i+L]*xp[L];
}
int dp[maxn][maxn];
int main()
{
int n;
init();
while(scanf("%d",&n)!=EOF)
{
if(n==0) break;
for(int i=0;i<n;i++) scanf("%s",str[i]);
for(int i=0;i<n;i++) strrev(str[i]);
make_hash(n);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
dp[i][j]=1;
int ans=1;
for(int i=1;i<n;i++)
{
for(int j=1;j<n;j++)
{
int tmp=dp[i-1][j-1];
for(int len=tmp;len>=0;len--)
{
ull tmp1=Get_hash1(i,j-len,len+1);
ull tmp2=Get_hash2(j,i-len,len+1);
if(tmp1==tmp2)
{
dp[i][j]=len+1;
break;
}
}
ans=max(ans,dp[i][j]);
}
}
printf("%d\n",ans);
}
return 0;
}
R把奶牛挤奶时间排个序 先按照挤奶时间从开始时间递增排序
按照Lis 的思想去更新答案即可
dp[i]代表到这个奶牛结尾产生的最大值
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define lc (rt<<1)
#define rc (rt<<11)
#define mid ((l+r)>>1)
typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 1025;
struct node
{
int l,r,v;
bool operator<(const node other) const
{
if(l==other.l) return r>other.r;
return l < other.l;
}
}arr[MAX_N];
int dp[MAX_N];
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int n,m,t,ans = 0;scanf("%d%d%d",&n,&m,&t);
for(int i = 1;i<=m;++i) scanf("%d%d%d",&arr[i].l,&arr[i].r,&arr[i].v),arr[i].r+=t;
sort(arr+1,arr+1+m);
for(int i = 1;i<=m;++i) dp[i] = arr[i].v;
for(int i = 1;i<=m;++i)
{
for(int j = 1;j<i;++j)
{
if(arr[i].l>=arr[j].r)
{
dp[i] = max(dp[i],dp[j] + arr[i].v);
}
}
}
for(int i = 1;i<=m;++i)
ans = max(ans,dp[i]);
printf("%d\n",ans);
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}