A.
题意:找到一个最长上升序列。
解法:最最最最暴力。。
#include <bits/stdc++.h>
#define LOCAL
#define ll long long
#define lll unsigned long long
#define MAX 1000009
#define eps 1e-8
#define INF 0x7fffffff
#define mod 1000000007
using namespace std;
int a[MAX];
int main()
{
int n;
cin>>n;
int sum = 1;
int _max = -1;
cin>>a[0];
int k = a[0];
for(int i = 1;i<n;i++)
{
cin>>a[i];
if(a[i]>=k)
{
sum++;
}
else
{
_max = max(_max, sum);
sum = 1;
}
k = a[i];
}
_max = max(_max, sum);
cout<<_max<<endl;
return 0;
}
B.
题意:找到任意元素之间绝对值小于d的集合的幸福值和的最大值。
解法:把m从小到大排序,然后二分查找 m[i] 和 m[i] + d - 1的位置,然后维护个前缀和,这样就能快速找到区间和了。
写的时候注意边界的处理
#include <bits/stdc++.h>
#define LOCAL
#define ll long long
#define lll unsigned long long
#define MAX 1000009
#define eps 1e-8
#define INF 0x7fffffff
#define mod 1000000007
using namespace std;
struct node{
ll m,s;
}p[MAX];
bool cmp(node a,node b)
{
return a.m < b.m;
}
ll sum[MAX];
ll x[MAX];
int main()
{
int n,d;
while(~scanf("%d%d",&n,&d))
{
for(int i = 0;i<n;i++)
{
cin>>p[i].m>>p[i].s;
}
sort(p,p+n,cmp);
sum[0] = p[0].s;
for(int i = 1;i<n;i++)
{
sum[i] = sum[i - 1] + p[i].s;
}
for(int i = 0;i<n;i++)
{
x[i] = p[i].m;
}
ll _max = -1;
for(int i = 0;i<n;i++)
{
int pos1 = lower_bound(x,x+n,p[i].m) - x;
int pos2 = upper_bound(x,x+n,p[i].m + d - 1) - x;
//cout<<pos1<<" "<<pos2 - 1<<endl;
if(pos1==pos2-1)
{
_max = max(_max,p[pos1].s);
}
else
{
if(pos1 == 0)
_max = max(_max,sum[pos2 - 1]);
else
_max = max(_max,sum[pos2 - 1] - sum[pos1 - 1]);
}
}
printf("%lld\n",_max);
}
return 0;
}
C.
题意:实质是从根节点出发到叶子节点的路径上,最长连续被标记的长度小于等于d的叶子节点数
解法:DFS 三个参数 当前结点 当前节点的父亲节点 最长连续被标记的长度
没有被标记的就清空
#include <bits/stdc++.h>
#define LOCAL
#define ll long long
#define lll unsigned long long
#define MAX 1000009
#define eps 1e-9
#define INF 0x7fffffff
#define mod 1000000007
using namespace std;
struct node
{
int num;
int to;
};
vector<int>g[MAX];
int vis[MAX];
int num[MAX];
int ans;
int n,d;
void dfs(int u,int sum,int fu)
{
if(sum > d)
return ;
if(g[u].size()==1&&u!=1)
ans++;
for(int i = 0;i<g[u].size();i++)
{
int v = g[u][i];
if(v==fu)continue;
if(vis[v])
dfs(v,sum+1,u);
else
dfs(v,0,u);
}
}
int main()
{
cin>>n>>d;
memset(vis,0,sizeof(vis));
for(int i = 1; i<=n; i++)
{
cin>>vis[i];
}
for(int i = 1; i<n; i++)
{
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
ans = 0;
dfs(1,vis[1],-1);
printf("%d\n",ans);
return 0;
}
D.
题意:n到菜选m道菜,且先选i 后选j 会额外得到 use[i][j]的奖励,求最大值
解法:状态压缩DP 第一维选取了哪些菜,第二维,最后一次选的菜是什么
#include <bits/stdc++.h>
#define LOCAL
#define ll long long
#define lll unsigned long long
#define MAX 1000009
#define eps 1e-8
#define INF 0x7fffffff
#define mod 1000000007
using namespace std;
ll dp[1<<18][18];//第一维选取了哪些菜,第二维,最后一次选的菜是什么
ll a[50];
ll use[50][50];
int main()
{
int n,m,k;
ll u,v,w;
while(~scanf("%d%d%d",&n,&m,&k))
{
for(int i = 0; i<n; i++) scanf("%lld",&a[i]);
for(int i = 0; i<k; i++)
{
scanf("%lld%lld%lld",&u,&v,&w);
--u;
--v;
use[u][v] = w;
}
for(int i = 0; i<n; i++)
{
dp[1<<i][i] = a[i];
}
for(int Status = 1; Status<(1<<n); Status++)
{
for(int i = 0; i<n; i++)
{
if(!(Status&(1<<i)))
{
for(int j = 0; j<n; j++)
{
if((Status&(1<<j)))
{
dp[Status|(1<<i)][i] = max(dp[Status|(1<<i)][i],dp[Status][j] + a[i] + use[j][i]);
}
}
}
}
}
ll _max = 0;
for(int Status = 0; Status<(1<<n); Status++)
{
int cnt = 0;
for(int i = 0; i<n; i++)
{
if(Status&(1<<i))
{
cnt++;
}
}
if(cnt==m)
{
for(int i = 0; i<n; i++)
{
_max = max(_max,dp[Status][i]);
}
}
}
printf("%lld\n",_max);
}
return 0;
}