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;
}
posted @ 2024-11-11 21:50  Kevinhwbb  阅读(5)  评论(0编辑  收藏  举报