A.Eshag Loves Big Arrays
题意:
每次都可以将子序列中大于平均数的数字删除,问最多可删除多少数字。
思路:
显然进行n次操作后只有最小值能留下来,记录最小值个数就行了。
代码如下:
#include <iostream>
#include <cstring>
#include <cmath>
#include <set>
#include <queue>
#include <vector>
#include <cstdio>
#include <queue>
#include <sstream>
#include <string>
#include <algorithm>
#include <map>
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define reps(i, a, b) for (int i = a; i >= b; i--)
using namespace std;
const int N = 2e4 + 7;
const int M = 2e2 + 7;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
typedef long long ll;
int cnt[N];
int main()
{
int t;
scanf("%d",&t);
while (t--){
memset(cnt,0,sizeof cnt);
int n;
scanf("%d",&n);
int x;
int mi=inf;
rep(i,1,n){
scanf("%d",&x);
cnt[x]++;
mi=min(mi,x);
}
printf("%d\n",n-cnt[mi]);
}
return 0;
}
B. Sifid and Strange Subsequences
题目
题目要求最长奇异序列的长度,奇异序列是满足任意两个元素差的绝对值都大于最大值的序列。
很明显负数和0都要加入,正数至多加入一个,并且0多于一个时不可加入正数,还要满足正数要小于等于负数的最小差。
#include <iostream>
#include <cstring>
#include <cmath>
#include <set>
#include <queue>
#include <vector>
#include <cstdio>
#include <queue>
#include <sstream>
#include <string>
#include <algorithm>
#include <map>
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define reps(i, a, b) for (int i = a; i >= b; i--)
using namespace std;
const int N = 2e5 + 7;
const int M = 2e2 + 7;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
typedef long long ll;
int num[N],nmb[N];
int main()
{
int t;
scanf("%d",&t);
while (t--){
int n,cnt=0,ct=0;
scanf("%d",&n);
rep(i,1,n){
scanf("%d",&num[i]);
if(num[i]<=0){
nmb[cnt++]=num[i];
if(num[i]==0)ct++;
}
}
sort(nmb,nmb+cnt);
int mi=inf;
rep(i,0,cnt-1){
if(i>0)mi=min(mi,abs(nmb[i]-nmb[i-1]));
if(i<cnt-1)mi=min(mi,abs(nmb[i+1]-nmb[i]));
}
if(ct<=1) {
rep(i, 1, n) {
if (num[i] > 0&&mi>=num[i]) {
cnt++;
break;
}
}
}
printf("%d\n",cnt);
}
return 0;
}
C.Parsa’s Humongous Tree.
树形dp
题目
题意:每个节点的取值范围为li,ri,美丽值是两个相邻节点差的绝对值,求最大美丽值和。
只用考虑区间端点值即可,这样每次决策就只有两种选择,很容易想到dp。dp[i][1 , 0]表示第i个节点,取左端点或右端点时的总美力值,则对于(u,v), 有:
dp[u][0]+=max(dp[v][1]+abs(r[v]-l[u]),dp[v][0]+abs(l[u]-l[v]))
dp[u][1]+=max(dp[v][1]+abs(r[u]-r[v]),dp[v][0]+abs(r[u]-l[v]))
#include <iostream>
#include <cstring>
#include <cmath>
#include <set>
#include <queue>
#include <vector>
#include <cstdio>
#include <queue>
#include <sstream>
#include <string>
#include <algorithm>
#include <map>
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define reps(i, a, b) for (int i = a; i >= b; i--)
using namespace std;
const int N = 2e5 + 7;
const int M = 2e2 + 7;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
typedef long long ll;
int l[N],r[N];
vector<ll>G[N];
ll dp[N][3];
bool vis[N];
void dfs(int u)
{
vis[u]=1;
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(!vis[v]){
dfs(v);//从叶子节点开始往上更新
dp[u][0]+=max(dp[v][1]+abs(r[v]-l[u]),dp[v][0]+abs(l[u]-l[v]));
dp[u][1]+=max(dp[v][1]+abs(r[u]-r[v]),dp[v][0]+abs(r[u]-l[v]));
}
}
}
int main()
{
int t;
scanf("%d",&t);
while (t--){
memset(dp,0,sizeof dp);
memset(vis,0,sizeof vis);
int n;
scanf("%d",&n);
rep(i,1,n){
scanf("%d%d",&l[i],&r[i]);
}
int u,v;
rep(i,1,n-1){
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1);
printf("%lld\n",max(dp[1][0],dp[1][1]));
rep(i,1,n)G[i].clear();//记得清空
}
return 0;
}