题意:给定数组a,数组b,要让a变为b,可以连续k个数字花费x全部清除,或者花费y相邻的数字小的消除。
首先可以考虑到
y
∗
k
y*k
y∗k与x的大小关系,决定了我们的策略,是个贪心,先预处理b[0],b[m+1],标记区间,len为一段区间的长度,一段区间内我们分析:
1:len<k,只能一个一个做,花费y,判断一下与端点的大小即可
2:len>=k,如果(
y
∗
k
>
=
x
y*k>=x
y∗k>=x)建议取第一种方法,由于每个数都不同,我们把(len%k)个数肯定可以全部y花费解决其余x。
否非优先y,如果都小于端点,全部y;否则留一个k长度就行。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=998244353;
const int MAXlen=1e5+10;
long double eps=1e-9;
int a[200100];
int b[200010];
int book[200010]={0};
map<int,int>hh;
int findMAX(int l,int r)
{
int MAX=0;
for(int i=l;i<=r;i++)
{
MAX=max(a[i],MAX);
}
return MAX;
}
int main()
{
int n,m,i,j,x,k,y;
scanf("%d %d",&n,&m);
scanf("%d %d %d",&x,&k,&y);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
hh[a[i]]=i;
}
b[0]=-2;
hh[b[0]]=0;
b[m+1]=-1;
hh[b[m+1]]=n+1;
for(i=1;i<=m;i++)
{
scanf("%d",&b[i]);
}
ll ans=0;
for(i=1;i<=m+1;i++)
{
int l=hh[b[i-1]],r=hh[b[i]];
if(r-l==1)
continue;
if(r<l)
{
printf("-1");
return 0;
}
int ghs=max(a[l],a[r]);
ll temp=y*k;
ll len=r-l-1;
int MAX=findMAX(l+1,r-1);
if(r-l-1<k)
{
if(MAX>a[l]&&MAX>a[r])
{
printf("-1");
return 0;
}
else
{
ans+=y*len;
}
continue;
}
else
{
if(y*k>=x)
{
ans+=(len/k)*x+(len-(len/k)*k)*y;
continue;
}
else
{
if(MAX<a[l]||MAX<a[r])
{
ans+=len*y;
}
else
{
ans+=(len-k)*y+x;
}
}
}
}
printf("%I64d",ans);
return 0;
}
题意:有m个塔,塔上有圆盘,圆盘从大到小递减排列(自下而上)。
定义了"难度":为将他们全部合并的操作次数。
m-1次询问,每次合并给定的两个塔的圆盘,剩余的”难度“是多少。
可以所谓的操作数,其实也就是找连续的数字在一起的当作一次。
往后合并aa,bb之后,遍历长度较小的那个塔设圆盘为v,如果大的塔里有v-1,v+1的值,那么v进去解决了v+1,v-1的贡献,就连续了。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=998244353;
const int MAXlen=1e5+10;
long double eps=1e-9;
int a[200100];
int cnt=0;
int id[200010];
vector< set<int> >hh(200100);
int main()
{
int n,m,i,j;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
hh[a[i]].insert(i);
}
for(i=1;i<=n;i=j)
{
j=i+1;
while(j<=n&&a[i]==a[j])
j++;
cnt++;
}
for(i=1;i<=m;i++)
id[i]=i;
printf("%d\n",cnt-1);
for(int uu=1;uu<m;uu++)
{
int aa,bb;
scanf("%d %d",&aa,&bb);
set<int>&s1=hh[aa];
set<int>&s2=hh[bb];
if(s1.size()<s2.size())
swap(s1,s2);
for(auto v:s2)
{
cnt-=s1.count(v-1)+s1.count(v+1);
}
for(auto v:s2)
{
s1.insert(v);
}
s2.clear();
printf("%d\n",cnt-1);
}
return 0;
}