CF 1313
Posted knife-rose
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF 1313相关的知识,希望对你有一定的参考价值。
偷偷摸一套题解。。。
A
给定三个颜色的数量,问能凑出多少钟不同的搭配
贪心,先拿最多的颜色搭配出需要颜色最少的组合
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=1e5+10,p=998244353;
int haku;
int a[4],sum;
inline void main()
{
haku=read();
while(haku--)
{
a[1]=read(),a[2]=read(),a[3]=read();
sort(a+1,a+4);
sum=0;
if(a[1]) --a[1],++sum;
if(a[2]) --a[2],++sum;
if(a[3]) --a[3],++sum;
if(a[2]&&a[3]) --a[2],--a[3],++sum;
if(a[1]&&a[3]) --a[1],--a[3],++sum;
if(a[1]&&a[2]) --a[1],--a[2],++sum;
if(a[1]&&a[2]&&a[3]) ++sum;
printf("%lld
",sum);
}
}
}
signed main()
{
red::main();
return 0;
}
B
最小排名:尽量让其他的人(sum=x+y+1),有些第一轮的数字做不到就让这些数字先把第二轮最小的浪费掉,得到排名(=max(1,x+y-n+1))
最大排名:尽量让其他人(sum=x+y),做不到的同理花掉最小的数字,得到排名(=min(n,z-1))
(x==1,y==1) 和 (x==n,y==n) 的时候都要特判。。
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=1e5+10,p=998244353;
int haku;
int n,x,y,z;
inline void main()
{
haku=read();
while(haku--)
{
n=read(),x=read(),y=read();
if(x==1&&y==1)
{
puts("1 1");
continue;
}
if(x==n&&y==n)
{
printf("%lld %lld
",n,n);
continue;
}
z=x+y;
if(x>y) swap(x,y);
int sum1=0,sum2=0;
sum1=max(1ll,z-n+1);
sum2=min(z-1,n);
printf("%lld %lld
",sum1,sum2);
}
}
}
signed main()
{
red::main();
return 0;
}
/*
1
5 5 1
*/
C
(s1[i])表示以(i)为峰,(1-i)的和,(s2[i])表示以(i)为峰,(i-n)的和,枚举中间点拼接一下
记得打完暴力打正解的时候把数组开大。。
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=5e5+10,p=998244353;
int haku;
int n,sum,ret,pos;
int a[N],c[N];
int st[N],top;
int s1[N],s2[N];
inline void main()
{
n=read();
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<=n;++i)
{
s1[i]=s1[i-1];
while(top&&a[i]<=a[st[top]])
{
s1[i]-=(st[top]-st[top-1])*a[st[top]];
--top;
}
s1[i]+=(i-st[top])*a[i];
st[++top]=i;
}
st[top=0]=n+1;
for(int i=n;i;--i)
{
s2[i]=s2[i+1];
while(top&&a[i]<=a[st[top]])
{
s2[i]-=(st[top-1]-st[top])*a[st[top]];
--top;
}
s2[i]+=(st[top]-i)*a[i];
st[++top]=i;
}
for(int i=0;i<=n;++i)
{
if(s1[i]+s2[i+1]>ret)
{
pos=a[i]>a[i+1]?i:i+1;
ret=s1[i]+s2[i+1];
}
}
c[pos]=a[pos];
for(int i=pos-1;i;--i) c[i]=min(a[i],c[i+1]);
for(int i=pos+1;i<=n;++i) c[i]=min(a[i],c[i-1]);
for(int i=1;i<=n;++i) printf("%lld ",c[i]);
}
}
signed main()
{
red::main();
return 0;
}
D
每个区间只会被覆盖(k)次,撞鸭一个区间被哪些线段覆盖,(f[i][s])表示区间([i,i+1])被s种线段覆盖后的最大价值
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=2e5+10,inf=1e9+7;
int n,m,k,s,now,ret;
int c[N],num;
int f[N],cnt[N];
int l[N],r[N],id[N];
vector<int> d[N];
inline void main()
{
n=read(),m=read(),k=read();s=1<<k;
for(int i=1;i<s;++i) cnt[i]=cnt[i>>1]+(i&1);
for(int i=1;i<=n;++i)
{
l[i]=read(),r[i]=read()+1;
c[++num]=l[i],c[++num]=r[i];
}
c[++num]=m;c[++num]=1;
sort(c+1,c+num+1);num=unique(c+1,c+num+1)-c-1;
for(int i=1;i<=n;++i)
{
l[i]=lower_bound(c+1,c+num+1,l[i])-c;
r[i]=lower_bound(c+1,c+num+1,r[i])-c;
for(int j=l[i];j<r[i];++j) d[j].push_back(i);
}
memset(f,0xcf,sizeof(f));f[0]=0;
for(int i=1;i<num;++i)
{
for(int j=0;j<k;++j)
if(id[j]&&r[id[j]]<=i) now^=1<<j,id[j]=0;
for(int j=0;j<s;++j)
if((j|now)!=now) f[j&now]=max(f[j&now],f[j]),f[j]=-inf;
for(int j=0;j<d[i].size();++j) if(l[d[i][j]]==i)
{
for(int p=0;p<k;++p) if(!id[p])
{
for(int l=s-1;~l;--l)
{
f[l|1<<p]=f[l];
}
id[p]=d[i][j],now|=1<<p;break;
}
}
for(int j=0;j<s;++j)
f[j]+=(cnt[j]&1)*(c[i+1]-c[i]);
}
for(int i=0;i<s;++i) ret=max(ret,f[i]);
printf("%lld
",ret);
}
}
signed main()
{
red::main();
return 0;
}
E
(f[i])表示(a)串以(i)开头与(s)串的最长公共前缀,(g[i])表示(b)串以(i)结尾与(s)串的最长公共后缀
由于两个区间必须有交,所以(l_1<=r_2)
由于两个区间长度之和等于(m),所以(r_2<=l_1+m-2)
对于一对固定的(l_1,r_2),对答案的贡献为(f[l_1]=g[r_2]-m+1)
[ret=sumlimits_{i=1}^{n}sumlimits_{j=i}^{min(n,i+m+2)}max(f[i]+g[j]-m+1,0)]
我们开两个(bit),用来记录([i,i+m-2])中(g[j])的数量和加和
显然对于(g[j]+1<m-f[i])的部分我们是不需要的,我们每次先对答案加上([m-f[i],m])区间内的(g[j])的和
再加上 (数量*(f[i]-m+1))
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=1e6+10,inf=1e9+7,base=131,mod=1e9+7;
int n,m,t,ret;
char a[N],b[N],s[N];
int nxt[N],f[N],g[N];
int pw[N],ha[N],hs[N];
inline void prepare(char *a,int *f)
{
int len=max(n,m);
for(int i=pw[0]=1;i<=len;++i) pw[i]=pw[i-1]*base%mod;
for(int i=1;i<=n;++i) ha[i]=(ha[i-1]*base+a[i])%mod;
for(int i=1;i<=m;++i) hs[i]=(hs[i-1]*base+s[i])%mod;
for(int i=1;i<=n;++i)
{
int l=i,r=n;
while(l<=r)
{
int t1=(ha[mid]-ha[i-1]*pw[mid-i+1]%mod+mod)%mod;
int t2=hs[mid-i+1];
if(t1==t2) f[i]=mid-i+1,l=mid+1;
else r=mid-1;
}
f[i]=min(f[i],m-1);
}
}
struct BIT
{
int tr[N];
BIT(){memset(tr,0,sizeof(tr));}
inline void update(int p,int k)
{
for(p++;p<N;p+=p&(-p)) tr[p]+=k;
}
inline int query(int p)
{
int ret=0;
for(p++;p;p-=p&(-p)) ret+=tr[p];
return ret;
}
}bit[2];
inline void main()
{
n=read(),m=read();
scanf("%s%s%s",a+1,b+1,s+1);
prepare(a,f);
reverse(s+1,s+m+1);reverse(b+1,b+n+1);
prepare(b,g);
reverse(g+1,g+n+1);
for(int i=n;i;--i)
{
bit[0].update(g[i],1);
bit[1].update(g[i],g[i]);
if(i+m-1<=n)
{
bit[0].update(g[i+m-1],-1);
bit[1].update(g[i+m-1],-g[i+m-1]);
}
int v=m-f[i];
ret+=bit[1].query(m)-bit[1].query(v-1);
ret-=(bit[0].query(m)-bit[0].query(v-1))*(v-1);
}
printf("%lld
",ret);
}
}
signed main()
{
red::main();
return 0;
}
以上是关于CF 1313的主要内容,如果未能解决你的问题,请参考以下文章