A
时间限制:1秒 空间限制:131072K
题目描述
Today HH becomes a shopper, and he wants to buy a lot.
HH has a bag that can carry at most w kilograms things in total, and he has d dollars.
Now he wants to buy n items,the ith item weights wi kilogram and costs ci dollars.
HHis not good at math so he asks you to tell him whether he can buy all the things and carry them with the bag.
输入描述:
The first line contains an positive integer T(1≤T≤10), represents there are T test cases.
For each test case:
The first line contains three positive integers n,w,d(1≤n≤100,1≤w≤100,1≤d≤100) - the number of items HH wants to buy, the max weight that his bag can carry, and the money he has.
The second line contains n integers w1,w2…wn(1≤wi≤100). The third line contains n integers c1,c2…cn(1≤ci≤100).
输出描述:
For each test case, output one line “YES” (without quotes) if HH is possible to buy all the items and carry them in his bag, and “NO” (without quotes) otherwise.
示例1
输入
2
4 12 17
1 2 4 5
5 4 6 2
4 11 17
1 2 4 5
5 4 6 2
输出
YES
NO
说明
In the first example all the items cost 17 dollars in total and weight 12 kilograms in total, HH has enough money and his bag can carry 12 kilogram things.
水题,01背包
代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)
const int MAXN = 1e3;
const int MAXM = 1e6;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
int dp[MAXN],cost[MAXN],val[MAXN];
int main(){
CLOSE();
// fread();
// fwrite();
int T;cin>>T;
while(T--){
int n,w,d;cin>>n>>w>>d;int sum=0;
for(int i=1;i<=n;i++) cin>>cost[i];
for(int i=1;i<=n;i++){
cin>>val[i];
sum+=val[i];
}
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
for(int j=w;j>=cost[i];j--)
dp[j]=max(dp[j],dp[j-cost[i]]+val[i]);
}
if(dp[w]==sum&&d>=sum) puts("YES");
else puts("NO");
}
return 0;
}
B
时间限制:4秒 空间限制:131072K
题目描述
Today HH is palying with a n×n matrix.
All the numbers of the matrix is 0 initial, and every time HH will do one of the following things:
1.make all the numbers in the k row become v
2.make all the numbers in the k column become v
Now HH wants to know what’s the final matrix after q options.
输入描述:
The first line contains an positive integer T(1≤T≤10), represents there are T test cases.
For each test case:
The first line contains two positive integers n,q(1≤n≤500,1≤q≤2*105) - the size of the matrix and the times of the options.
Then q lines following, for each line contains three integers op,k,v(1≤op≤2,1≤k≤n,1≤v≤100).
if op=1, then HH will change all the numbers in the k row into v
if op=2, then HH will change all the numbers in the k column into v
输出描述:
For each test case, you should output n lines , each line n numbers , indicating the final matrix, note that for each line ,you should print exactly one blank between two numbers.
示例1
输入
1
3 3
1 2 3
2 2 1
1 1 3
输出
3 3 3
3 1 3
0 1 0
思维题,我们只需要记录,行和列最后更新的值就行了。
具体的看代码
代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)
const int MAXN = 1000+10;
const int MAXM = 1e6;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
int row[MAXN],col[MAXN];
int vis1[MAXN],vis2[MAXN];
int main(){
// fread();
// fwrite();
int T;scanf("%d",&T);
while(T--){
memset(row,0,sizeof(row));
memset(col,0,sizeof(col));
memset(vis1,0,sizeof(vis1));
memset(vis2,0,sizeof(vis2));
int n,q ; scanf("%d%d",&n,&q);
int op,v,k;
int id=1; // 这个时间戳 来记录谁是最后更新
while(q--){
scanf("%d%d%d",&op,&k,&v);
if(op==1) {
row[k]=v;
vis1[k]=id++;
}else {
col[k]=v;
vis2[k]=id++;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(vis1[i]>vis2[j]) printf("%d",row[i]);
else printf("%d",col[j]);
if(j!=n) putchar(' ');
}
puts("");
}
}
return 0;
}
E
时间限制:2秒 空间限制:131072K
题目描述
Today HH becomes a designer, and he faces a problem so he asks you for help.
Treeisland is a country with n cities and n−1 two-way road and from any city you can go to any other cities.
HH the designer is going to design a plan to divide n city into n/2 pairs so that the sum of the length between the n/2 pairs city is minimum.
Now HH has finished it but he doesn’t know whether it’s true so he ask you to calculate it together.
It’s guaranteed that n is even.
输入描述:
The first line contains an positive integer T(1≤T≤100), represents there are T test cases.
For each test case: The first line contains an positive integer n(1≤n≤104), represents the number of cities in Treeisland, it’s guarantee that n is even.
Then n−1 lines followed. Each line contains three positive integer u, v and len, (u≠v,1≤u≤n,1≤v≤n,1≤len≤109)indicating there is a road of length len between u and v.
It’s guarantee you can get to any city from any city.
输出描述:
For each test case, output in one line an integer, represent the minimum sum of length.
示例1
输入
2
4
1 2 5
2 3 8
3 4 6
6
1 3 5
3 2 3
4 5 4
4 3 9
4 6 10
输出
11
31
说明
In the first example, you can divide them into (1,2), and (3,4), then the minimum sum of length is 5+6=11
In the second example, you can divide them into (1,3),(2,4),(5,6), hen the minimum sum of length is 5+(3+9)+(10+4)=31
题意 给一棵偶数节点的树,将其分为两两的点对,每组点对的贡献就是两个节点之间的距离,求最小的总贡献。
不会写,没思路。 看了别人博客, 想法很巧妙。
假设以每个节点u为根节点的子树,我们可以知道,如果这个子树的节点数(包含u节点)为奇数,那么这个u的和其父节点所连的边权一定会被经过。
代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)
const int MAXN = 1e4+10;
const int MAXM = 1e6;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
struct Edge {
int from,to,val,next;
}edge[MAXN<<1];
int head[MAXN],top;
int n,m;
void init(){
memset(head,-1,sizeof(head));
top=0;
}
void addedge(int a,int b,int c){
Edge e={a,b,c,head[a]};
edge[top]=e;head[a]=top++;
}
void getmap(){
int a,b,c;
while(m--){
cin>>a>>b>>c;
addedge(a,b,c);
addedge(b,a,c);
}
}
LL ans; int size[MAXN];
void dfs(int fa,int u,int w){
size[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next){
Edge e=edge[i];
if(e.to==fa) continue;
dfs(u,e.to,e.val);
size[u]+=size[e.to];
}
if(size[u]&1) ans+=w;
}
int main(){
CLOSE();
// fread();
// fwrite();
int T ;cin>>T;
while(T--){
cin>>n;m=n-1;
init();
getmap();
ans=0;
dfs(-1,1,0);
cout<<ans<<endl;
}
return 0;
}
F
时间限制:2秒 空间限制:131072K
题目描述
Today HH finds a non-decreasing sequence(a1,a2….an,ai≤ai+1), he thinks it’s not beautiful so he wants to make it beautiful.
To make it, HH will choose exactly one number and move it forward at least k steps(i.e. you can move ai to aj if k≤i−j), and then he defines the beautiful value F(n) as
HH asks you to calculate max(F(n))
输入描述:
The first line contains an positive integer T(1≤T≤10), represents there are T test cases.
For each test case:
The first line contains two positive integers n,k(1≤ n ≤ 105,1 ≤ k < n ) ,the length of the sequence ,the least steps you need to move.
The second line contains n integers a1,a2…an(1≤ a i≤108) - the sequence.
输出描述:
For each test case, you should output the max F(n).
示例1
输入
3
5 3
1 1 3 4 5
5 2
1 1 3 4 5
5 1
1 1 3 4 5
输出
46
50
53
说明
In the first example, you can move the fifth number 4 for 3 steps and make the sequence become [4,1,1,3,5], then the beautiful value is 4×1+1×2+1×3+3×4+5×5=46.
You can also move the fifth number to make it become [1,5,1,3,4], the beautiful value is also 46.
In the second example, you can move the fifth number 5 for 2 steps and make the sequence become [1,1,5,3,4]
In the second example, you can move the second number 1 for 1 steps and then the sequence is still [1,1,3,4,5]
备注:
scanf is commended。
思维+贪心。
很明显,大数越在后面越好。
我们可以枚举所有数,都让它恰好向前移动k位置。 再取最大值就行。
这里有一点关键就是,枚举每个数的时候,怎么计算移动后的总体值,肯定不能够暴力,随便找一组数据我们就可以找到规律,具体的看代码。
代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)
const int MAXN = 1e5+10;
const int MAXM = 1e6;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
LL max(LL a,LL b) { return a>b?a:b; }
LL pre[MAXN];
LL arr[MAXN];
int main(){
CLOSE();
// fread();
// fwrite();
int T;scanf("%d",&T);
while(T--){
int n,k;scanf("%d%d",&n,&k);
pre[0]=0; LL perfect=0;
for(int i=1;i<=n;i++){
scanf("%lld",&arr[i]);
pre[i]=pre[i-1]+arr[i];
perfect+=i*arr[i];
}
// printf("%lld\n",perfect);
LL ans=0;
for(int i=k+1;i<=n;i++){
int l=i-k;
int r=i-1;
LL temp= perfect-i*arr[i]+l*arr[i]+pre[r]-pre[l-1] ;// 规律
//printf("l=%d r=%d\n",l,r);
ans=max(temp,ans);
}
printf("%lld\n",ans);
}
return 0;
}
H
时间限制:2秒 空间限制:131072K
题目描述
There is a magic maze that its roads is unidirectional and you will not arrive the same resting area if you walk alongthe road (the maze is acyclic). There are n resting areas and m roads in themaze. Some roads make you get treasure, while others make you lost treasure. You should pick the place to set out and get treasure as much as possible.
Note that for each road you can go through only once.
输入描述:
The first line: the number of case T (1≤T≤110 )
In each test case:
The first line is two integers: the number of resting area n, the number of roads m(1≤n≤1000, 0≤m≤n×(n−1)÷2) m lines follow, each with three integers: the beginning u, the end v, treasure w(0 ≤ u < n,0 ≤ v < n ,−1000 ≤ w ≤ 1000)
输出描述:
T lines, each with an integer what is the maximum treasure
示例1
输入
2
5 4
0 1 -10
1 2 10
2 3 10
3 4 -10
4 4
0 1 4
0 2 5
2 3 -2
3 1 4
输出
20
7
说明
In the first example, you can go 1 ->2 >3, then the ans is 10+10=20
In the second example, you can go 0 ->2 ->3>-1, then the ans is 5−2+4=7
求DAG图的最长路
topo+树形dp
代码
#include<bits/stdc++.h>
using namespace std ;
typedef long long LL ;
const int MAXN = 1000+10 ;
const int MAXM = 100000+10 ;
const int mod = 1e9+7 ;
struct Edge {
int from,to,val,next;
}edge[MAXN*MAXN];
int head[MAXN],top;
void init(){
memset(head,-1,sizeof(head));
top=0;
}
void addedge(int a,int b,int c){
edge[top].from=a;edge[top].to=b;
edge[top].val=c;edge[top].next=head[a];
head[a]=top++;
}
int n,m;
int in[MAXN];
int val[MAXN];
void work(){
queue<int>Q;
memset(val,0,sizeof(val));
for(int i=1;i<=n;i++) if(!in[i]) Q.push(i);
while(!Q.empty()){
int now=Q.front();Q.pop();
for(int i=head[now];i!=-1;i=edge[i].next){
Edge e=edge[i];
val[e.to]=max(val[e.to],val[now]+e.val);// DP思想
if(--in[e.to]==0) Q.push(e.to);
}
}
int ans=0;
for(int i=1;i<=n;i++) ans=max(ans,val[i]);
printf("%d\n",ans);
}
int main(){
int T;scanf("%d",&T);
while(T--){
init();
memset(in,0,sizeof(in)) ;
scanf("%d%d",&n,&m);
while(m--){
int a,b,c;scanf("%d%d%d",&a,&b,&c);
a++;b++;
addedge(a,b,c);
in[b]++;
}
work();
}
return 0;
}
K
时间限制:2秒 空间限制:131072K
题目描述
Today HH is learning a new data structure named segment tree, which is often used to solve segment problem, here comes one:
Gave you an unordered sequence of length n,(a1,a2,…,an), now you are supposed to calculate how many segment L,R are there satisfies two conditions :
1.the length of the segment is k(i.e. R−L+1=k).
2.the number between L and R(both including) appears at least q times in total.
HH thinks the problem is too easy so he gives the problem to you.
输入描述:
The first line contains an positive integer T(1≤T≤10), represents there are T test cases.
For each test case: The first line contains three positive integers n,k,q(1≤n≤100,1≤k≤100,1≤q≤100),the length of the sequence , the length of the segment [l,R], and the times required to appear. The second line contains n integers a1,a2…an(1≤ai≤100) - the sequence.
输出描述:
For each test case, output one line an integer : the number of segment satisfies both conditions.
示例1
输入
3
5 3 2
2 3 2 4 5
5 3 3
2 3 2 4 5
5 3 6
2 3 2 4 5
输出
4
3
0
说明
In the first example , we can find 4 segments:
[1,3],1 appears 0 time,2 appears 2 times,3 appears 1 time,so 3 times in total.
[2,4],4 times in total.[3,5] 3 times in total.[4,6],2 times in total.
In the second example, we can find:
[1,3],[2,4],[3,5].
In the third example, we can’t find any.
很明显我们要维护定长区间里的点个数,因为数据是静态的,所以我们直接打表前缀和就行了。
代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)
const int MAXN = 1e3+10;
const int MAXM = 1e6;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
int pre[MAXN]; // 从pre[i] 表示 区间[1,i]中有几个点
int cnt[MAXN];
int main(){
CLOSE();
// fread();
// fwrite();
int T;scanf("%d",&T);
while(T--){
memset(cnt,0,sizeof(cnt));
memset(pre,0,sizeof(pre));
int n,k,q;scanf("%d%d%d",&n,&k,&q);
int R=0;
for(int i=1;i<=n;i++){
int a;scanf("%d",&a);
cnt[a]++;
R=max(R,a);
}
for(int i=1;i<=R+k;i++)
pre[i]=pre[i-1]+cnt[i];
int ans=0;
for(int i=1;i<=R;i++){
if(pre[i+k-1]-pre[i-1]>=q){
ans++;
}
}
printf("%d\n",ans);
}
return 0;
}