第一题: HDU 5804 链接
0 ~ 商品总和之间的任意价格都可以取到 每次判断记录是否大于总和即可
代码:
#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
#define sf scanf
#define pf printf
using namespace std;
typedef long long LL;
int main(){
int T,n,m;
LL temp,sum;
sf("%d",&T);
while( T-- ){
sum = 0;
sf("%d %d",&n,&m);
for(int i = 0;i < n;++i){
sf("%I64d",&temp);
sum += temp;
}
for(int i = 0;i < m;++i){
sf("%I64d",&temp);
if(temp > sum){
pf("1");
}else pf("0");
}
pf("\n");
}
return 0;
}
第二题: HDU 5805 链接
记录前缀和后缀最大值f,g 枚举所有去掉点 求左端点 的 前缀最大值 、右端点后缀最大值,左右端点距离 的MAX 求和即可
long long 没注意 被hack了
然后hack我的人 我已经关注你了!
代码:
#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
#define sf scanf
#define pf printf
#define fabs(n) ((n) > 0 ? n : -(n))
using namespace std;
typedef long long LL;
const int maxn = 100000 + 5;
int A[maxn];
int pre_max[maxn];
int tail_max[maxn];
int main(){
int T;
sf("%d",&T);
while( T-- ){
int n;sf("%d",&n);
for(int i = 0;i < n;++i){
sf("%d",&A[i]);
}
pre_max[0] = 0;
for(int i = 1;i < n;++i){
pre_max[i] = max(pre_max[i - 1],fabs(A[i - 1] - A[i]));
}
tail_max[n - 1] = 0;
for(int i = n - 2;i >= 0;--i){
tail_max[i] = max(tail_max[i + 1],fabs(A[i + 1] - A[i]));
}
LL ans = 0;
for(int i = 1;i < n - 1;++i){
ans += max(pre_max[i - 1],max( tail_max[i + 1] ,fabs(A[i - 1] - A[i + 1])) );
}
ans += tail_max[1] + pre_max[n - 2];
pf("%I64d\n",ans);
}
return 0;
}
第三题: HDU 5806 链接
和题解的比起来我的有些复杂
枚举区间坐端点 之后二分查找合法的最左右端点p
∑(n - p + 1)就是答案了
代码:
#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
#define sf scanf
#define pf printf
using namespace std;
const int maxn = 200000 + 5;
int sum[maxn];
typedef long long LL;
int main(){
// freopen("read.txt","r",stdin);
int T;
sf("%d",&T);
int n,k,m;
while( T-- ){
sf("%d%d%d",&n,&m,&k);
for(int i = 1;i <= n;++i){
sf("%d",&sum[0]);
if(sum[0] >= m){
sum[i] = 1;
}else sum[i] = 0;
}
sum[0] = 0;
for(int i = 1;i <= n;++i){
sum[i] = sum[i - 1] + sum[i];
}
// for(int i = 1;i <= n;++i) pf("%d\n",sum[i]);
LL ans = 0;
for(int i = 1;i <= n;++i){
// pf("aa");
int p = lower_bound(sum + 1,sum + n + 1,sum[i - 1] + k) - sum;
ans += n - p + 1;
}
pf("%I64d\n",ans);
}
return 0;
}
第四题:HDU 5807 链接
简单的DAG图 初始化将两个城市不能通信的状态值 设为0
dp[i][j][k] = ∑dp[a][b][c]
加了一个状态p表示此时是第几个人移动到 0表示3人都移动完成 加快的算法速度
代码:
#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
#define sf scanf
#define pf printf
using namespace std;
int fabs(int n){
return n > 0 ? n : -n;
}
typedef long long LL;
const int maxn = 51;
const LL mod = 998244353;
LL dp[maxn][maxn][maxn][4];
int kk[maxn];
vector<int> Adj[maxn];
LL get_next_point(int a,int b,int c,int lable){
LL &ans = dp[a][b][c][lable];
if(ans != -1) return ans;
ans = 0;
if(lable == 0){
ans = 1;
ans += get_next_point(a,b,c,1);
ans %= mod;
// pf("%d %d %d %lld\n",a,b,c,ans);
return ans;
}
if(lable == 1){
for(int i = 0;i < Adj[a].size();++i){
ans += get_next_point(Adj[a][i],b,c,2);
ans %= mod;
}
}
if(lable == 2){
for(int i = 0;i < Adj[b].size();++i){
ans += get_next_point(a,Adj[b][i],c,3);
ans %= mod;
}
}
if(lable == 3){
for(int i = 0;i < Adj[c].size();++i){
ans += get_next_point(a,b,Adj[c][i],0);
ans %= mod;
}
}
return ans;
}
void init(){
for(int i = 0;i < maxn;++i){
Adj[i].clear();
}
}
int main(){
// freopen("read.txt","r",stdin);
int T;
int n,m,k,q;
sf("%d",&T);
while( T-- ){
init();
sf("%d%d%d%d",&n,&m,&k,&q);
for(int i = 1;i <= n;++i){
sf("%d",&kk[i]);
}
for(int i = 0;i < m;++i){
int u,v;sf("%d%d",&u,&v);
Adj[u].push_back(v);
}
memset(dp,-1,sizeof(dp));
for(int i = 1;i <= n;++i){
for(int j = 1;j <= n;++j){
if(fabs( kk[i] - kk[j] ) > k){
// pf("%d %d\n",i,j);
for(int p = 1;p <= n;++p){
dp[i][j][p][0] = dp[i][p][j][0] = dp[p][i][j][0] = 0;
}
}
}
}
for(int i = 0;i < q;++i){
int a,b,c;
sf("%d%d%d",&a,&b,&c);
printf("%lld\n",get_next_point(a,b,c,0));
}
}
return 0;
}