LeetCode第 443 场周赛题解

3502. 到达每个位置的最小费用

思路:取前缀最小值就行

class Solution {
public:
const int maxn=2e5+100;
public:
    vector<int> minCosts(vector<int>& cost) {
        int n=cost.size();
        vector<int>mn(n,1e9);
        mn[0]=cost[0];
        for(int i=1;i<n;i++)
        {
            mn[i]=min(mn[i-1],cost[i]);
        }
        return mn;
    }
};

3503. 子字符串连接后的最长回文串 I

思路:暴力枚举就行

class Solution {
public:
bool check(string s)
{
    int len=s.length();
    for(int i=0,j=len-1;i<j;i++,j--)
    {
        if(s[i]!=s[j])
        return false;
    }
    return true;
}
public:
    int longestPalindrome(string s, string t) {
        int len1=s.length(),len2=t.length();
        int ans=1;
        for(int i=0;i<len1;i++)
        {
            string s1="";
            for(int j=i;j<len1;j++)
            {
                s1+=s[j];
                if(check(s1))
                {
                    ans=max(ans,(int)s1.length());
                }
                for(int k=0;k<len2;k++)
                {
                    string s2="";
                    for(int p=k;p<len2;p++)
                    {
                        s2+=t[p];
                        if(check(s2))
                        ans=max(ans,(int)s2.length());
                        if(check(s1+s2))
                        ans=max(ans,(int)s1.length()+(int)s2.length());
                    }
                }
            }
        }
        return ans;
    }
};

3504. 子字符串连接后的最长回文串 II

思路:dp一下就行

class Solution {
public:
    int longestPalindrome(string s, string t) {
        reverse(t.begin(),t.end());
        auto cal=[&](const string &s,const string &t)
        {
            const int n=s.length();
            const int m=t.length();
            vector<vector<int>>f(n+1,vector<int>(m+1,0));
            for(int i=n-1;i>=0;i--)
            {
                for(int j=m-1;j>=0;j--)
                {
                    if(s[i]==t[j])
                    f[i][j]=f[i+1][j+1]+1;
                    else f[i][j]=0;
                }
            }
            vector<int>p(n+1,0);
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<m;j++)
                p[i]=max(p[i],f[i][j]);
            }
            vector<int>h(n+1,0);
            for(int i=0;i<n;i++)
            {
                for(int l=i,r=i;l>=0&&r<n&&s[l]==s[r];l--,r++)
                h[l]=max(h[l],r-l+1);
            }
            for(int i=0;i<n;i++)
            {
                for(int l=i,r=i+1;l>=0&&r<n&&s[l]==s[r];l--,r++)
                h[l]=max(h[l],r-l+1);
            }
            int ans=1;
            for(int i=0;i<n;i++)
            ans=max(ans,h[i]);
            for(int i=0;i<n;i++)
            {
                for(int j=1;j<=p[i];j++)
                ans=max(ans,j*2+h[i+j]);
            }
            return ans;
        };
        return max(cal(s,t),cal(t,s));
    }
};

3505. 使 K 个子数组内元素相等的最少操作数

思路:dp+树状数组求到中位数的差之和

class Solution {
public:
static const int maxn=2e5+100;
int n;
vector<long long>vt;
long long dp[maxn][20];
long long b[maxn],p[maxn];
long long f[maxn];
long long tr1[maxn],tr2[maxn];
int find(long long x)
{
	int pos=lower_bound(vt.begin(),vt.end(),x)-vt.begin()+1;
	return pos;
}
int lowbit(int x)
{
	return x&(-x);
}
void add1(int x,int v)
{
	for(int i=x;i<=n;i+=lowbit(i))
	tr1[i]+=v;
}
long long query1(int x)
{
	long long res=0;
	for(int i=x;i;i-=lowbit(i))
	res+=tr1[i];
	return res;
}
void add2(int x,long long v)
{
	for(int i=x;i<=n;i+=lowbit(i))
	tr2[i]+=v;
	
}
long long query2(int x)
{
	long long res=0;
	for(int i=x;i;i-=lowbit(i))
	res+=tr2[i];
	return res;
}
long long cal(int id,const vector<int>& nums,int x,int k)
{
	int l=1,r=n;
	int pos=n;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(query1(mid)>=(x+1)/2)
		{
			pos=min(pos,mid);
			r=mid-1;
		}else l=mid+1;
	}
	long long cnt1=query1(pos-1);
	long long cnt2=query1(n)-query1(pos);
	long long v1=cnt1*nums[p[pos]]-query2(pos-1);
	long long v2=(query2(n)-query2(pos))-cnt2*nums[p[pos]];
	return v1+v2;
}
    long long minOperations(vector<int>& nums, int x, int k) {
        n=nums.size();
        for(int i=0;i<n;i++)
        {
            vt.push_back(nums[i]);
        }
        sort(vt.begin(),vt.end());
        vt.erase(unique(vt.begin(),vt.end()),vt.end());
        for(int i=0;i<n;i++)
        {
   	        b[i]=find(nums[i]);
   	        p[b[i]]=i;
        }
        for(int i=0;i<x;i++)
        {
   	        add1(b[i],1);
   	        add2(b[i],nums[i]);
        }
        f[0]=cal(0,nums,x,k);
        for(int i=1;i+x-1<n;i++)
        {
   	        add1(b[i-1],-1);
   	        add2(b[i-1],-nums[i-1]);
   	        add1(b[i+x-1],1);
   	        add2(b[i+x-1],nums[i+x-1]);
   	        f[i]=cal(i,nums,x,k);
        }
        for(int i=0;i<n;i++)
        {
   	        for(int j=0;j<=k;j++)
   	            dp[i][j]=1e17;
        }
        for(int i=0;i<x-1;i++)
            dp[i][0]=0;
        for(int i=x-1;i<n;i++)
        {
   	        for(int j=0;j<=k;j++)
   	            dp[i][j]=dp[i-1][j];
   	        if(i<x-1)
   	            continue;
   	        for(int j=1;j<=k;j++)
   	        {
   	            long long v=(i>=x?dp[i-x][j-1]:(j==1?0:1e17));
   	            dp[i][j]=min(dp[i][j],v+f[i-x+1]);	
	        }
        }
        return dp[n-1][k];
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值