2024.11.11
今日总结
1:http://www.nfls.com.cn:10611/p/P667
这道题主要考察的是思维,在考虑时要注意观察规律,适当用贪心的思想想问题
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n,ans;
int a[N],l[N],r[N];
int main()
{
freopen("lamp.in","r",stdin);
freopen("lamp.out","w",stdout);
scanf("%d",&n);
for(int i = 1;i <= n;i ++)
scanf("%d",&a[i]);
a[0] = a[1];
for(int i = 1;i <= n;i ++)
{
if(a[i] != a[i - 1]) l[i] = l[i - 1] + 1;
else l[i] = 1;
ans = max(ans,l[i]);
}
a[n + 1] = a[n];
for(int i = n;i >= 1;i --)
{
if(a[i] != a[i + 1]) r[i] = r[i + 1] + 1;
else r[i] = 1;
ans = max(ans,r[i]);
}
for(int i = 1;i <= n;i ++)
{
int L = i,R = r[i] + i - 1,now = r[i];
if(a[L] == a[L - 1]) now += l[L - 1];
if(a[R] == a[R + 1]) now += r[R + 1];
ans = max(ans,now);
}
printf("%d\n",ans);
return 0;
}
2:http://www.nfls.com.cn:10611/p/P12394
这道题是一道Dp+二分的题目,主要考察的是二分对程序的优化
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
int n,m;
ll a[N],b[N];
vector<ll> vec;
int main()
{
freopen("were.in","r",stdin);
freopen("were.out","w",stdout);
scanf("%d",&n);
for(int i = 1;i <= n;i ++)
scanf("%lld",&a[i]);
for(int i = 1;i <= n;i ++)
scanf("%lld",&b[i]);
for(int i = 1;i <= n;i ++)
{
if(vec.empty() || vec.back() * b[vec.size()] < a[i]) vec.push_back(a[i]);
else
{
int pos = lower_bound(vec.begin(),vec.end(),a[i]) - vec.begin();
if(pos == 0) vec.front() = a[i];
else if(a[i] > vec[pos - 1] * b[pos]) vec[pos] = a[i];
else vec[pos - 1] = min(vec[pos - 1],a[i]);
}
}
printf("%lld\n",vec.size());
return 0;
}
3:[https://www.luogu.com.cn/problem/P2736](Raucous Rockers)
这道题考察的二维01背包,再有容积的DP问题时要倒序循环求DP方程
点击查看代码
// 定义dp[j][k]来记录在第j个专辑中k内存最多能存多少首歌
#include<bits/stdc++.h>
using namespace std;
const int N = 25;
int n,c,m;
int t[N];
int dp[N][N];
int main()
{
scanf("%d%d%d",&n,&c,&m);
for(int i = 1;i <= n;i ++)
scanf("%d",&t[i]);
for(int i = 1;i <= n;i ++)
for(int j = m;j >= 1;j --)
for(int k = c;k >= t[i];k --)
dp[j][k] = max(dp[j][k],max(dp[j - 1][c] + 1,dp[j][k - t[i]] + 1));
int Max = -1;
for(int i = 1;i <= m;i ++)
for(int j = 1;j <= c;j ++)
Max = max(Max,dp[i][j]);
printf("%d\n",Max);
return 0;
}
4:https://www.luogu.com.cn/problem/P4802
这道题考察的是状压Dp,当题目中出现多种状态时可以考虑转换为一种通用状态类似二进制,也可为其他,将状态单独循环
点击查看代码
//dp[i][j]表示在i状态下到j的最长路
#include<bits/stdc++.h>
using namespace std;
int n,m;
int dp[1 << 18][20],g[20][20];
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= m;i ++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
g[u][v] = w;
}
for(int i = 1;i < (1 << n);i ++)
for(int j = 0;j < n;j ++)
dp[i][j] = -1;
dp[1][0] = 0;
for(int i = 1;i < (1 << n);i ++)
{
for(int j = 0;j < n;j ++)
{
if(dp[i][j] == -1) continue;//如果没有路就直接退出
for(int k = 0;k < n;k ++)
{
if(!(i & (1 << k)) && g[j][k])
{
dp[i | (1 << k)][k] = max(dp[i | (1 << k)][k],dp[i][j] + g[j][k]);
}
}
}
}
int ans = 0;
for(int i = 1;i < (1 << n);i ++)
{
if((i & 1) && (i & (1 << (n - 1)))) ans = max(ans,dp[i][n - 1]);
}
printf("%d\n",ans);
return 0;
}
5:https://hydro.ac/d/topoac/p/NOIP1007
这道题主要考察二分找边界的能力 ,贪心求中位数(之前没做到过)
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N=1e5+10,Inf=1e18;
int a[N];
int n,m,mx;
int sc[N],sv[N];
int Ans=Inf;
inline PII Sum(int l,int r)
{
if(l>r) return {0,0};
int x=lower_bound(a+1,a+1+n,l)-a,y=upper_bound(a+1,a+1+n,r)-a-1;
if(x>y) return {0,0};
// printf("Sum: %d %d %d %d\n",l,r,sv[y]-sv[x-1],sc[y]-sc[x-1]);
return {sv[y]-sv[x-1],sc[y]-sc[x-1]};
}
inline int calc(int l,int r,int v)
{
PII a=Sum(l,v),b=Sum(v+1,r);
int w=v*a.second-a.first+b.first-v*b.second;
// printf("calc: %d %d %d: %d\n",l,r,v,w);
return w;
}
inline void solve(vector<int> &vec)
{
int sz=vec.size();
int cost=0;
for(int i=0;i<sz;i++)
{
if(i==0)
{
cost+=calc(vec[i],(vec[i]+vec[i+1])/2,vec[i]);
}
else if(i==sz-1)
{
cost+=calc((vec[i]+vec[i-1])/2+1,vec[i],vec[i]);
}
else
{
cost+=calc((vec[i]+vec[i-1])/2+1,(vec[i]+vec[i+1])/2,vec[i]);
}
}
Ans=min(Ans,cost);
// printf("cost: %d\n",cost);
}
inline bool check(int l,int r,int ql,int qr)
{
if(r<ql) return false;
if(l>qr) return false;
return true;
}
signed main()
{
// freopen("ex_power.in","r",stdin);
freopen("power.in","r",stdin);
freopen("power.out","w",stdout);
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n;
a[++m]=1;
for(int i=1,x;i<=n;i++)
{
cin>>x;
if(x!=1) a[++m]=x,mx=max(mx,x);
}
n=m;
sort(a+1,a+1+n);
for(int i=1;i<=n;i++) sc[i]=sc[i-1]+1,sv[i]=sv[i-1]+a[i];
int d=2;
for(;(d*d+d)/2+1<=mx;d++)
{
vector<int> vec;
int x=1;
vec.push_back(1);
while(x<=mx)
{
x*=d;
vec.push_back(x);
}
// printf("solve: %d\n",d);
solve(vec);
}
// exit(0);
for(int i=1;i<n;i++)
{
int l=a[i]*2,r=(a[i+1]*2-1),w=calc(1,a[i],1);
l=max(l,d);
if(l>r) continue;
int ql=a[(i+1+n)/2],qr=a[(i+2+n)/2];
if(check(l,r,ql,qr)) w+=calc(a[i+1],a[n],ql);
else w+=min(calc(a[i+1],a[n],l),calc(a[i+1],a[n],r));
// printf("[%d %d %d]\n",l,r,w);
Ans=min(Ans,w);
}
Ans=min(Ans,calc(1,n,a[n]));
cout<<Ans<<"\n";
return 0;
}