A
简单题,比较买个人密钥和团体密钥时哪个成本低就好,主要最后团体密钥要看看是不足三人时买一个团体密钥更优还是买个人密钥更优。
#include<iostream>
#include<queue>
#include<deque>
#include<bitset>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<unordered_map>
#include<set>
#include<map>
#include<ctime>
#include<random>
#include<vector>
#include<utility>
#define f(i,a,b) for(ll i=a;i<=b;i++)
using ll = long long;
using db = double;
ll rd(){ll x=0,w=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-'){w=-1;}c=getchar();}while('0'<=c&&c<='9'){x=x*10+(c-'0');c=getchar();}return x*w;}
using namespace std;
const ll MX =1e5+7;
const ll mod = 1e9+7;
mt19937 mrd(time(0));
namespace Wunsch{
ll n,T,k,m,ans,cnt;
ll ksm(ll x,ll y){
ll res=1;
while(y){
if(y&1)res=res*x%mod;
x=x*x%mod;
y>>=1;
}
return res;
}
void work(){
n=rd();m=rd();k=rd();
cout<<min(n*m,n/3*k+min((n-n/3*3)*m,n%3==0?0:k))<<endl;
return ;
}
bool main(){
T=rd();
while(T--)work();
return 1;
}
}
bool amiya=Wunsch::main();
int main(){;}
B
首先容易发现4是一定要删去的。
然后发现因为100是4的倍数,所以说一个数是4的倍数当且仅当后两位能被4整除。
就发现序列中不能出现32和12。
众所周知,最少删除次数 = 原串长度 − 最长美丽子序列长度。
然后我们就可以发现美丽子序列的形式一定为前面全是2后面是1和3,下面考虑如何构造最长美丽子序列。
首次原串中的4要全删掉,然后枚举分割点,分割点前只要2分割点后只要1和3,求最大值就好。
#include<iostream>
#include<queue>
#include<deque>
#include<bitset>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<unordered_map>
#include<set>
#include<map>
#include<ctime>
#include<random>
#include<vector>
#include<utility>
#define f(i,a,b) for(ll i=a;i<=b;i++)
using ll = long long;
using db = double;
ll rd(){ll x=0,w=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-'){w=-1;}c=getchar();}while('0'<=c&&c<='9'){x=x*10+(c-'0');c=getchar();}return x*w;}
using namespace std;
const ll MX =1e5+7;
const ll mod = 1e9+7;
mt19937 mrd(time(0));
namespace Wunsch{
ll n,T,k,m,ans,cnt;
ll ksm(ll x,ll y){
ll res=1;
while(y){
if(y&1)res=res*x%mod;
x=x*x%mod;
y>>=1;
}
return res;
}
string s;
void work(){
cin>>s;n=s.size();
s=" "+s;
ll cnt4=0;ll cnt2=0;
f(i,1,n){
if(s[i]!='4')cnt++;
if(s[i]=='2')cnt2++;
}
ll p=0;
ll p2=0;
ll L=cnt-cnt2;//初始答案为只要1和3
f(i,1,n){
if(s[i]=='4')continue;
p++;
if(s[i]=='2')p2++;
if(cnt-cnt2-p+2*p2>L)L=cnt-cnt2-p+2*p2;//当前长度更长就更新ans,只要1和3的数量-从这个位置往前1和3的数量+从这个位置往前2的数量
}
cout<<n-L<<endl;
cnt=0;
return ;
}
bool main(){
T=rd();
while(T--)work();
return 1;
}
}
bool amiya=Wunsch::main();
int main(){;}
C
发现每组牌选了后一定全部用于构建这个环才是最优,要求环尽可能大所以能选的一定要选上才是最优,就发现只有单个的一张牌不能直接选,这种牌必须放在四个一样的牌的中间。所以我们统计这种合法的空隙有多少个,就可以得到最多能放下几张这种单个的牌,总牌数-放不下的牌数就是环的大小。
注意当只有一种牌数量大于2时合法空隙会因为首尾相连多一个。
#include<iostream>
#include<queue>
#include<deque>
#include<bitset>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<unordered_map>
#include<set>
#include<map>
#include<ctime>
#include<random>
#include<vector>
#include<utility>
#define f(i,a,b) for(ll i=a;i<=b;i++)
using ll = long long;
using db = double;
ll rd(){ll x=0,w=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-'){w=-1;}c=getchar();}while('0'<=c&&c<='9'){x=x*10+(c-'0');c=getchar();}return x*w;}
using namespace std;
const ll MX =5e5+7;
const ll mod = 1e9+7;
mt19937 mrd(time(0));
namespace Wunsch{
ll n,T,k,m,ans,cnt,num;
ll a[MX];
void work(){
n=rd();
cnt=ans=num=0;
f(i,1,n){
num+=a[i]=rd();
if(a[i]==1)cnt++;
else{
ans+=(a[i]>>1)-1;
}
}
if(cnt==n-1)ans++;
if(num-max(0ll,cnt-ans)<3)ans=0;
else ans=num-max(0ll,cnt-ans);
cout<<ans<<endl;
return ;
}
bool main(){
T=rd();
while(T--)work();
return 1;
}
}
bool amiya=Wunsch::main();
int main(){;}
D
可以发现当满足条件时也一定满足条件。
我们只考虑两人进度相同的情况,因为只有进度相同时才会对答案产生贡献。
假设我们已经固定了左端点 L,并且从左到右模拟,维护两人当前都需要的下一集编号(初始为 1)。每一天根据 决定是否观看,以及是否合法。这个过程可以一直进行到某一天 R,使得从 L 到 R 都是合法的,而第 R+1 天就会违法。那么 R 就是以 L 为左端点的最大合法右端点。显然,对于这个 L,所有右端点 [L, R] 都是合法的,共有 R - L + 1 个区间。
然后我们考虑怎么快速求出每个L对应的 R,我们发现可以倒叙处理,在一开始所有右端点默认n,然后我们维护这个 cur数组。当我们处理到第 i 天时,已经知道了从第 i+1 天开始,任意进度 x 对应的最大右端点,即 cur[x],表示从第 i+1 天开始,如果两人当前需要看的集数都是 x,那么可以一直合法地看到第 cur[x] 天(包含这一天)。
然后我们把当前这一天考虑进来,此时要进行分讨。
- 时,如果此时俩人该同时看这一集就会在这一天同时看,如果都没看到就会同时跳过,也就是说算上这一天并不会导致区间变成违法区间,可以直接继承
cur[x]=cur[x+1]。 - 时,我们发现仅对进度为a[i]和b[i]的时候有影响,此时他们的最大右端点要缩小到
i-1。
更新完i之后,cur[1] 就表示从第 i 天开始,初始进度为 1 的最大合法右端点。我们直接统计答案即可。
#include<iostream>
#include<queue>
#include<deque>
#include<bitset>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<unordered_map>
#include<set>
#include<map>
#include<ctime>
#include<random>
#include<vector>
#include<utility>
#define f(i,a,b) for(ll i=a;i<=b;i++)
using ll = long long;
using db = double;
ll rd(){ll x=0,w=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-'){w=-1;}c=getchar();}while('0'<=c&&c<='9'){x=x*10+(c-'0');c=getchar();}return x*w;}
using namespace std;
const ll MX =5e5+7;
const ll mod = 1e9+7;
mt19937 mrd(time(0));
namespace Wunsch{
ll n,T,k,m,ans,cnt;
ll a[MX],b[MX];
void work(){
n=rd();
f(i,1,n)a[i]=rd();
f(i,1,n)b[i]=rd();
vector<ll>cur(n+2,n);
ans=0;
for(int i=n;i>=1;i--){
if(a[i]==b[i]){
cur[a[i]]=cur[a[i]+1];
}
else{
cur[a[i]]=i-1;
cur[b[i]]=i-1;
}
ans+=cur[1]-i+1;
}
cout<<ans<<endl;
return ;
}
bool main(){
T=rd();
while(T--)work();
return 1;
}
}
bool amiya=Wunsch::main();
int main(){;}
E和F之后补(如果我会的话)
