8.18总结
泡泡堂
这道题有点像田忌赛马,但不全是。
贪心策略:
如果我方最强强于对方最强,ans+=2;
如果我方最弱强于对方最弱,ans+=2;
否则最弱打最强送死为其他人创造机会
AC Code
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int N=1e5+5;
int n,a[N],b[N];
int main()
{
// freopen("bubble.in","r",stdin);
// freopen("bubble.out","w",stdout);
n=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=n;i++)b[i]=read();
sort(a+1,a+n+1);
sort(b+1,b+n+1);
int ans=0,l1=1,r1=1;
int l2=n,r2=n;
while(l1<=l2&&r1<=r2)
{
if(a[l1]>b[r1]){
ans+=2;l1++,r1++;
}
else if(a[l2]>b[r2])
{
ans+=2;l2--,r2--;
}
else if(a[l1]==b[r2])
{
ans++;
l1++;r2--;
}
else l1++,r2--;
}
printf("%d ",ans);
ans=0,l1=r1=1;
l2=r2=n;
while(l1<=l2&&r1<=r2)
{
if(b[l1]>a[r1]){
ans+=2;l1++,r1++;
}
else if(b[l2]>a[r2])
{
ans+=2;l2--,r2--;
}
else if(b[l1]==a[r2])
{
ans++;
l1++;r2--;
}
else l1++,r2--;
}
printf("%d\n",n*2-ans);
return 0;
}
苹果树
真就有了结论后很快做出来,可惜考试时推不出结论
根据大佬的推论,我们可以得到一个式子:
把这个式子简化一下可以得到:
预处理一下组合数就可以很快求出答案
AC Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline ll read()
{
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int N=2005;
ll n,p,ans,m[N],c[N][N];
int main()
{
n=read(),p=read();
m[0]=1;
for(int i=1;i<=n;i++)
m[i]=m[i-1]*i%p;
for(int i=0;i<=n;i++)c[i][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
c[i][j]=(c[i-1][j-1]+c[i-1][j])%p;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n-i+1;j++)
{
ans+=j*(n-j)%p*m[j]%p*c[n-i][j-1]%p*m[n-j-1]%p*i%p*(i-1)%p;
ans%=p;
}
}
cout<<ans<<endl;
return 0;
}
字符合并
因为合并的区间之间互不干扰,且,所以我们考虑区间dp。因为,所以我们考虑状压dp。所以这道题是区间dp+状压dp。
设计状态:表示把区间[l,r]合并成状态s的最大价值
因为对于一个长为len的序列,我们最终一定会把它合并成一个长为的序列,所以状态s不超过。
枚举中间节点t,我们可以得到状态转移方程为:
当时,长为len的序列可以合并为一个字符,需要单独枚举最大价值
AC Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline ll read()
{
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int N=305;
const ll inf=0x3f3f3f3f3f3f3f3f;
ll n,k,c[N],w[N];
ll f[N][N][N];
char a[N];
int main()
{
n=read(),k=read();
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=0;i<(1<<k);i++)
{
c[i]=read(),w[i]=read();
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int p=0;p<(1<<k);p++)
f[i][j][p]=-inf;
}
}
for(int i=1;i<=n;i++)f[i][i][a[i]-'0']=0;
for(int len=2;len<=n;len++)
{
for(int l=1;l<=n-len+1;l++)
{
int r=l+len-1;
int len_=(len-1)%(k-1);
if(len_==0)len_=k-1;
for(int s=r;s>l;s-=k-1)
{
for(int p=0;p<(1<<len_);p++)
{
f[l][r][p*2]=max(f[l][r][p*2],f[s][r][0]+f[l][s-1][p]);
f[l][r][p*2+1]=max(f[l][r][p*2+1],f[s][r][1]+f[l][s-1][p]);
}
}
if(len_==k-1)
{
ll tmp1=-inf,tmp2=-inf;
for(int p=0;p<(1<<k);p++)
{
if(f[l][r][p]!=-inf)
{
if(c[p]==1)
{
tmp2=max(tmp2,f[l][r][p]+w[p]);
}
else
{
tmp1=max(tmp1,f[l][r][p]+w[p]);
}
}
}
f[l][r][0]=tmp1,f[l][r][1]=tmp2;
}
}
}
ll ans=-inf;
for(int i=0;i<(1<<k);i++)
{
ans=max(ans,f[1][n][i]);
}
cout<<ans<<endl;
return 0;
}
脑洞治疗仪
万万没想到,我50pts的原因是数组没开够
线段树维护修改操作,注意先挖后补
AC Code
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int N=2e5+5;
int n,m;
struct ww{
int l,r,sum,lm,rm,len;
int dat,tag;
}tr[N*8];
void updat(int p)
{
tr[p].sum=max(max(tr[p<<1].sum,tr[p<<1|1].sum),tr[p<<1].rm+tr[p<<1|1].lm);
tr[p].dat=tr[p<<1].dat+tr[p<<1|1].dat;
if(tr[p<<1].sum==tr[p<<1].len)
{
tr[p].lm=tr[p<<1].len+tr[p<<1|1].lm;
}
else tr[p].lm=tr[p<<1].lm;
if(tr[p<<1|1].sum==tr[p<<1|1].len)
{
tr[p].rm=tr[p<<1|1].len+tr[p<<1].rm;
}
else tr[p].rm=tr[p<<1|1].rm;
}
void build(int p,int l,int r)
{
tr[p].l=l,tr[p].r=r;
tr[p].len=r-l+1;
if(l==r)return ;
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
updat(p);
}
void pushdown(int p)
{
if(tr[p].tag==1)
{
tr[p<<1].tag=1;
tr[p<<1].sum=tr[p<<1].lm=tr[p<<1].rm=tr[p<<1].dat=tr[p<<1].len;
tr[p<<1|1].tag=1;
tr[p<<1|1].sum=tr[p<<1|1].lm=tr[p<<1|1].rm=tr[p<<1|1].dat=tr[p<<1|1].len;
tr[p].tag=0;
}
if(tr[p].tag==2)
{
tr[p<<1].tag=2;
tr[p<<1].sum=tr[p<<1].lm=tr[p<<1].rm=tr[p<<1].dat=0;
tr[p<<1|1].tag=2;
tr[p<<1|1].sum=tr[p<<1|1].lm=tr[p<<1|1].rm=tr[p<<1|1].dat=0;
tr[p].tag=0;
}
}
void change1(int p,int l,int r)
{
int l1=tr[p].l,r1=tr[p].r;
if(r1<l||r<l1)return ;
if(l<=l1&&r1<=r)
{
pushdown(p);
tr[p].tag=1;
tr[p].sum=tr[p].lm=tr[p].rm=tr[p].dat=tr[p].len;
return ;
}
pushdown(p);
int mid=(l1+r1)>>1;
if(l<=mid)change1(p<<1,l,r);
if(r>mid)change1(p<<1|1,l,r);
updat(p);
}
ww ask1(int p,int l,int r)
{
int l1=tr[p].l,r1=tr[p].r;
if(l<=l1&&r1<=r)
{
pushdown(p);
return tr[p];
}
pushdown(p);
ww ans,tr1,tr2;
int o1=0,o2=0;
int mid=(l1+r1)>>1;
if(l<=mid)
{
tr1=ask1(p<<1,l,r);
o1=1;
}
if(r>mid)
{
tr2=ask1(p<<1|1,l,r);
o2=1;
}
updat(p);
if(o1==0)return tr2;
if(o2==0)return tr1;
ans.sum=max(max(tr1.sum,tr2.sum),tr1.rm+tr2.lm);
ans.len=tr1.len+tr2.len;
if(tr1.sum==tr1.len)
{
ans.lm=tr1.len+tr2.lm;
}
else ans.lm=tr1.lm;
if(tr2.sum==tr2.len)
{
ans.rm=tr2.len+tr1.rm;
}
else ans.rm=tr2.rm;
return ans;
}
int ask2(int p,int l,int r)
{
int l1=tr[p].l,r1=tr[p].r;
if(r1<l||r<l1)return 0;
if(l<=l1&&r1<=r)
{
pushdown(p);
return tr[p].dat;
}
pushdown(p);
int ans=0;
int mid=(l1+r1)>>1;
if(l<=mid)ans+=ask2(p<<1,l,r);
if(r>mid)ans+=ask2(p<<1|1,l,r);
updat(p);
return ans;
}
int dat1;
void change2(int p,int l,int r)
{
int l1=tr[p].l,r1=tr[p].r;
if(r1<l||r<l1)return ;
if(dat1==0)return ;
if(l<=l1&&r1<=r&&tr[p].dat<=dat1)
{
dat1-=tr[p].dat;
pushdown(p);
tr[p].tag=2;
tr[p].sum=tr[p].dat=tr[p].lm=tr[p].rm=0;
return ;
}
pushdown(p);
int mid=(l1+r1)>>1;
if(l<=mid)change2(p<<1,l,r);
if(r>mid)change2(p<<1|1,l,r);
updat(p);
}
int main()
{
// freopen("head.in","r",stdin);
// freopen("head.out","w",stdout);
n=read(),m=read();
int opt,l,r;
build(1,1,n);
for(int i=1;i<=m;i++)
{
opt=read(),l=read(),r=read();
if(opt==0)
{
change1(1,l,r);
}
else if(opt==1)
{
int l1,r1;
l1=read(),r1=read();
dat1=r-l+1-ask2(1,l,r);
change1(1,l,r);
change2(1,l1,r1);
}
else
{
int tmp=ask1(1,l,r).sum;
printf("%d\n",tmp);
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步