每日一题
储物点的距离
https://ac.nowcoder.com/acm/problem/14683
思路:
1:首先预处理三个前缀和,a--前i个储物点的距离和,x_sum--前i个储物点的东西搬到第一个储物点的和,n_sum前i个储物点的东西和.
2:判断x与l和r的大小,如果x>=r,那么就先把[l,r]的东西全部搬到储物点1去,然后在全部搬到x点去,我们可以发现对于每个在[l,r]里面的j,[1,j]是重复搬了的,那么我们要减去,也就是减去x_sum[r]+x_sum[l-1]。
3:如果x<=l,也是先把[l,r]的东西全部搬到储物点1去,然后在全部搬到x点去,同理我们可以发现所有东西在[1,x]是重复搬了的,也就是减去(n_sum[r] - n_sum[l-1])*a[x].
4:如果l<x<r,和2,3算法相同。
#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#define LL long long
#define inf 0x3f3f3f3f
//void lowit(x){return x&(-x)};
const int mod = 1e9+7;
using namespace std;
//781
LL a[200005],n_sum[200005],x_sum[200005];
int main()
{
int n,m;
cin >> n >> m;
a[1] = 0;
for(int i = 2; i <= n; i++) cin >> a[i];
for(int i = 2; i <= n; i++) a[i] = (a[i-1] + a[i]) % mod;
for(int i = 1; i <= n; i++){
cin >> n_sum[i];
x_sum[i] = (n_sum[i]*a[i] % mod + x_sum[i-1] % mod) % mod;
n_sum[i] = (n_sum[i - 1] + n_sum[i]) % mod;
}
while(m--){
int x,l,r;
LL ans = 0;
cin >> x >> l >> r;
if(x >= r){
ans = (((n_sum[r] - n_sum[l - 1] + mod) % mod * a[x] % mod) - (x_sum[r] - x_sum[l - 1] + mod) % mod + mod) % mod;
}
else if(x <= l){
ans = ((x_sum[r] - x_sum[l - 1] + mod) % mod - ((n_sum[r] - n_sum[l - 1] + mod) % mod * a[x] % mod) + mod)% mod;
}
else{
ans = (((n_sum[x] - n_sum[l - 1] + mod) % mod * a[x] % mod) - (x_sum[x] - x_sum[l - 1] + mod) % mod + mod) % mod;
ans = (ans % mod + ((x_sum[r] - x_sum[x - 1] + mod) % mod) - ((n_sum[r] - n_sum[x - 1] + mod) % mod * a[x] % mod) + mod) % mod;
}
cout << ans % mod << endl;
}
return 0;
}
旅游 树形dp
https://ac.nowcoder.com/acm/problem/15748
#include <bits/stdc++.h>
#include <iostream>
#define LL long long
#define inf 0x3f
const int mod = 1e9+7;
using namespace std;
int dp[500005][2];
vector<int>a[500005];
void dfs(int s,int f)
{
dp[s][1] = 1;
for(int i = 0; i < a[s].size(); i++){
if(a[s][i] == f) continue;
dfs(a[s][i],s);
dp[s][0] += max(dp[a[s][i]][1],dp[a[s][i]][0]);
dp[s][1] += dp[a[s][i]][0];
}
}
int main()
{
int s,x,y,n;
cin >> n >> s;
for(int i = 1; i < n; i++){
cin >> x >> y;
a[x].push_back(y);
a[y].push_back(x);
}
dfs(s,-1);
cout << dp[s][1];
return 0;
} Protecting the flowers
https://ac.nowcoder.com/acm/problem/25043
题目大意:每个牛牵回牛舍需要Ti分钟,牵某个牛时,其他牛会继续吃花,问怎样牵牛可以使得破坏的花最少。
思路:对于两头牛c1,c2,当先牵c1时,破坏花的数量为sum1=c1d2,当先牵走c2时,sum2=c2d1,比较sum1和sum2,优先选择小的,所有我们先按ci*dj从小到大排序。
#include <bits/stdc++.h>
using namespace std;
struct S{
int t,d;
}s[100005];
bool cmp(S a,S b)
{
return a.t*b.d < b.t*a.d;
}
int main()
{
int n;
long long sum = 0;
cin >> n;
for(int i = 1; i <= n; i++) cin >> s[i].t >> s[i].d,sum += s[i].d;
sort(s+1,s+n+1,cmp);
long long ans = 0;
for(int i = 1; i <= n; i++){
sum -= s[i].d;
ans += sum * s[i].t * 2;
}
cout << ans;
return 0;
} codeforce:01背包
https://ac.nowcoder.com/acm/problem/21314
思路:和上一题类似,假设两道题目c1,c2,先做c1,总得分sum1=mp1-pp1t1+mp2-pp2(t2+t1),sum2=mp2-pp2t2+mp1-pp1(t1+t2),sum1-sum2=pp1t2-pp2t1,假设sum1>sum2,即pp1t2>pp2t1,按这个排序选题做即可.
#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#define LL long long
#define inf 0x3f3f3f3f
//void lowit(x){return x&(-x)};
const int mod = 1e9+7;
using namespace std;
//781
struct node{
LL mp,pp,t;
}s[55];
bool cmp(node a,node b)
{
return a.t * b.pp < b.t * a.pp;
}
LL dp[100005];
int main()
{
int n,t;
cin >> n >> t;
for(int i = 1; i <= n; i++) cin >> s[i].mp;
for(int i = 1; i <= n; i++) cin >> s[i].pp;
for(int i = 1; i <= n; i++) cin >> s[i].t;
sort(s+1,s+n+1,cmp);
LL ans = 0;
for(int i = 1; i <= n; i++){
for(int j = t; j >= s[i].t; j--){
dp[j] = max(dp[j],dp[j - s[i].t] + s[i].mp - s[i].pp*j);
}
}
for(int i = 0; i <= t; i++) ans = max(ans,dp[i]);
cout << ans;
return 0;
}
滑动窗口
#include <bits/stdc++.h>
#include <iostream>
const int Max = 100 * 100 * 100 + 5;
#define LL long long
const int mod = 1e9+7;
//const int inx = INT_MAX;
using namespace std;
// srand(time(NULL));
// m = rand() % 1000 + 1;
//定义i i(A) i+n i+n(B) i+n+n i+n+n(C)
//bitset<Max>s,q;
deque<int>q1,q2;
int b1[1000005],b2[1000005];
int a[1000005];
int main()
{
int n,k,i,op,sp;
cin >> n >> k;
for(i = 1; i <= n; i++){
cin >> a[i];
}
for(i = 1; i <= n; i++){
while(!q1.empty() && i - k >= q1.front()){
q1.pop_front();
}
while(!q1.empty() && a[i] <= a[q1.back()]){
q1.pop_back();
}
while(!q2.empty() && i - k >= q2.front()){
q2.pop_front();
}
while(!q2.empty() && a[i] >= a[q2.back()]){
q2.pop_back();
}
q1.push_back(i);
q2.push_back(i);
if(i >= k) b1[i] = (a[q1.front()]);
if(i >= k) b2[i] = (a[q2.front()]);
}
for(i = k; i <= n; i++){
cout << b1[i] << " ";
}
cout << endl;
for(i = k; i <= n; i++){
cout << b2[i] << " ";
}
return 0;
}
wyh的物品:二分+01分数规划
#include <bits/stdc++.h>
#include <algorithm>
#define mod 1000000007
#define LL long long
using namespace std;
int v[100005],w[100005],n,k;
double v1[100005];
bool cmp(double a,double b)
{
return a > b;
}
bool pd(double x)
{
int i;
for(i = 1; i <= n; i++){
v1[i] = v[i] * 1.0 - x * w[i];
}
double sum = 0;
sort(v1 + 1,v1 + n + 1,cmp);
for(i = 1; i <= k; i++){
sum += v1[i];
}
if(sum >= 0) return true;
else return false;
}
int main()
{
int T,i;
cin >> T;
while(T--){
cin >> n >> k;
for(i = 1; i <= n; i++){
cin >> w[i] >> v[i];
}
double l = 0,r = 100000;
while(abs(l - r) > 0.00000001){
double mid = (l + r) / 2.0;
if(pd(mid)) l = mid;
else r = mid;
}
printf("%.2f\n",l);
}
return 0;
}
查看11道真题和解析