Educational Codeforces Round 111 (Rated for Div. 2)
A
显然对于第\(i\)个数为\(2i+1\)最优。
那么直接模拟即可。
code:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 200000
#define M 50000
#define mod 1000000000
#define mod2 39989
#define eps (1e-7)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define R(x) (rand()*rand()%x+1)
using namespace std;
int T,n;
int main(){
freopen("1.in","r",stdin);
re int i;scanf("%d",&T);while(T--){
scanf("%d",&n);for(i=1;;i+=2) if((i+1)*(i+1)/4>=n)break;printf("%d\n",(i+1)/2);
}
}
B
首先这个\(a\)其实是假的因为\(an\)的答案铁定逃不掉的。
所以对\(b\)正负分类讨论然后看是一个一个拿还是一段一起拿最优即可。
code:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 200000
#define M 50000
#define mod 1000000000
#define mod2 39989
#define eps (1e-7)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define R(x) (rand()*rand()%x+1)
using namespace std;
int T,n,a,b,now,tot,pus;char s[N+5];
int main(){
freopen("1.in","r",stdin);
re int i;scanf("%d",&T);while(T--){
scanf("%d%d%d",&n,&a,&b);scanf("%s",s+1);
if(b>0) printf("%d\n",(a+b)*n);
else{
tot=0;for(i=2;i<=n;i++)tot+=(s[i]!=s[i-1]);tot++;printf("%d\n",a*n+b*(tot/2+1));
}
}
}
C
这个东西化简一下就是子区间内没有三个数满足\(i\leq j\leq k\)且\(a_i\leq a_j\leq a_k\)或递减
那么这个东西你枚举中间那个然后左右两边用单调栈处理出左右最近的小于等于和大于等于,然后就可以算出以这个点为中心的最小不合法,那么所有在这个外面的都不合法。
那么直接前缀min扫一遍算答案即可。
code:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 200000
#define M 50000
#define mod 1000000000
#define mod2 39989
#define eps (1e-7)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define R(x) (rand()*rand()%x+1)
using namespace std;
int T,n,A[N+5],st[N+5],sh,l1[N+5],r1[N+5],l2[N+5],r2[N+5],Minn[N+5],now;ll ans;
int main(){
freopen("1.in","r",stdin);
re int i;scanf("%d",&T);while(T--){
scanf("%d",&n);for(i=1;i<=n;i++) scanf("%d",&A[i]),Minn[i]=1e9;ans=0;
for(i=1;i<=n;i++) l1[i]=l2[i]=0,r1[i]=r2[i]=n+1;
for(i=1;i<=n;i++){
while(sh&&A[st[sh]]>A[i])sh--;l1[i]=st[sh];st[++sh]=i;
}sh=0;
for(i=1;i<=n;i++){
while(sh&&A[st[sh]]>=A[i])r1[st[sh]]=i,sh--;st[++sh]=i;
}sh=0;
for(i=1;i<=n;i++){
while(sh&&A[st[sh]]<A[i])sh--;l2[i]=st[sh];st[++sh]=i;
}sh=0;
for(i=1;i<=n;i++){
while(sh&&A[st[sh]]<=A[i])r2[st[sh]]=i,sh--;st[++sh]=i;
}sh=0;
for(i=1;i<=n;i++)Minn[l1[i]]=min(Minn[l1[i]],r2[i]),Minn[l2[i]]=min(Minn[l2[i]],r1[i]);now=n+1;
for(i=n;i;i--)now=min(now,Minn[i]),ans+=now-i;
printf("%lld\n",ans);
}
}
D
太屑了吧其实是蛮一眼的结果调到考试结束还没调出来。
可以发现我们要求的序列就是满足\(b_i=a_i-i\)相反数最大的序列。
那么这个就是\(\frac{n}{2}\)个正\(\frac{n+1}{2}\)个负数,或者当\(n\)为奇数时反过来。
这个直接枚举边界算答案即可,注意边界细节。
code:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 200000
#define M 50000
#define mod 1000000007
#define eps (1e-7)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define R(x) (rand()*rand()%x+1)
using namespace std;
int T,n,rs,x,y,nowx,nowy;ll ans,tot,pus,frc[N+5],inv[N+5],l,r;
I ll mpow(ll x,int y=mod-2){ll ans=1;while(y) (y&1)&&(ans=ans*x%mod),y>>=1,x=x*x%mod;return ans;}
int main(){
freopen("1.in","r",stdin);
re int i;scanf("%d",&T);frc[0]=1;for(i=1;i<=N;i++) frc[i]=frc[i-1]*i%mod;inv[N]=mpow(frc[N]);for(i=N-1;~i;i--) inv[i]=inv[i+1]*(i+1)%mod;
while(T--){
scanf("%d%lld%lld",&n,&l,&r);rs=max(min(1-l,r-n),1);
ans=(rs-1)*frc[n]%mod*inv[n/2]%mod*inv[(n+1)/2]%mod;x=rs+l;y=r-rs;
while(1){
if(x>y+1||y+1<(n)/2||x-1>(n)/2)break;nowx=max(x,1);nowy=min(y,n);
pus=nowy-nowx+1;ans+=frc[pus]*inv[pus-(n/2-nowx+1)]%mod*inv[n/2-nowx+1]%mod;
/*printf("%d %d %lld %lld\n",x,y,(n/2-nowx+1),frc[pus]*inv[pus-(n/2-nowx+1)]%mod*inv[n/2-nowx+1]%mod);*/x++;y--;
}
if(n&1){
rs=max(min(1-l,r-n),1);
ans+=(rs-1)*frc[n]%mod*inv[n/2]%mod*inv[(n+1)/2]%mod;x=rs+l;y=r-rs;
while(1){
if(x>y+1||y+1<(n+1)/2||x-1>(n+1)/2)break;nowx=max(x,1);nowy=min(y,n);
pus=nowy-nowx+1;ans+=frc[pus]*inv[pus-((n+1)/2-nowx+1)]%mod*inv[((n+1)/2-nowx+1)]%mod;
/*printf("%d %d %lld %lld\n",x,y,pus,frc[pus]*inv[pus-((n+1)/2-nowx+1)]%mod*inv[((n+1)/2-nowx+1)]%mod);*/x++;y--;
}
}
printf("%lld\n",ans%mod);
}
}
E
觉得很套路的一道题。
首先这种最大最小肯定是二分。然后变成判定性问题。
这个\(k\)这么小肯定是拿来状压的。
首先我们预处理出\(F_{i,j}\)为从\(i\)开始满足第\(j\)个字符个数大于等于\(mid\)的最近位置。
然后设\(dp_{k}\)为已经满足了集合\(k\)的最近位置。
这个东西直接转移即可,最后判一下能不能到\(2^k-1\)
时间复杂度\(O((n+2^k)klogn)\)
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 200000
#define K 17
#define mod 1000000000
#define mod2 39989
#define eps (1e-7)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int n,m,k,x,y,z,l,r,mid,B[N+5],F[N+5][K+5],dp[1<<K+1],rs,tot;char c[N+5];
I int check(int mid){
re int i,j;for(i=0;i<k;i++) {
for(j=1;j<=n;j++)B[j]=(c[j]=='?'||c[j]=='a'+i);for(j=n;j;j--) B[j]&&(B[j]=(B[j+1]?B[j+1]:j));
for(rs=n+1,j=n;j;j--){
if(B[j]-j+1>=mid)rs=j+mid-1;F[j][i]=rs;
}
}Me(dp,0x3f);dp[0]=0;
for(i=0;i<(1<<k);i++){
if(dp[i]>=n) continue;for(j=0;j<k;j++){
if(i&(1<<j)) continue;dp[i|(1<<j)]=min(dp[i|(1<<j)],F[dp[i]+1][j]);
}
}
return dp[(1<<k)-1]<=n;
}
int main(){
freopen("1.in","r",stdin);
re int i;scanf("%d%d",&n,&k);scanf("%s",c+1);l=0;r=n/k+1;
while(l+1<r) mid=l+r>>1,(check(mid)?l:r)=mid;printf("%d\n",l);
}
F
原来觉得这个题是最短路然后一点思路没有。
点开了题解发现是个MST,因为上课讲了Boruvka然后就觉得不可能是。
想了一下prim只能做到\(O(n^2)\),克鲁斯卡尔更屑。
又看了一眼发现是真的......
然后这个过程开个set维护即可。时间复杂度\(O(nlog^2n)\)
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 200000
#define K 17
#define mod 1000000000
#define mod2 39989
#define eps (1e-7)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int n,m,d,cnt,x,y,z,now,un,wn,A[N+5],fa[N+5],Ans[N+5],S,To[N+5],W[N+5],Fr[N+5];vector<int> F[N+5];
struct ques{int w,id;bool operator <(const ques &s)const{return (w==s.w)?id<s.id:w<s.w;}};set<ques> G;
I int Getfa(int x){return x==fa[x]?x:fa[x]=Getfa(fa[x]);} set<ques>::it pus;
struct yyy{int to,w,z;};
struct ljb{
int head,h[N+5];yyy f[N+5<<1];
I void add(int x,int y,int z){f[++head]=(yyy){y,z,h[x]};h[x]=head;}
}s;
I void dfs(int x,int last){
yyy tmp;for(int i=s.h[x];i;i=tmp.z) tmp=s.f[i],tmp.to^last&&(Ans[tmp.to]=max(Ans[x],tmp.w),dfs(tmp.to,x),0);
}
int main(){
freopen("1.in","r",stdin);
re int i,j;scanf("%d%d%d%d",&n,&m,&S,&d);cnt=n;for(i=1;i<=n;i++) scanf("%d",&A[i]),G.insert((ques){A[i],i}),fa[i]=i;
while(cnt^1){
for(i=1;i<=n;i++) F[i].clear();for(i=1;i<=n;i++) F[Getfa(i)].push_back(i);//printf("%d\n",cnt);
for(i=1;i<=n;i++){
W[i]=1e9;for(j=0;j<F[i].size();j++) now=F[i][j],G.erase((ques){A[now],now});
for(j=0;j<F[i].size();j++){
now=F[i][j];pus=G.lower_bound((ques){A[now]-d,0});
if(pus!=G.end()) (*pus).w-A[now]+d<W[i]&&(W[i]=(*pus).w-A[now]+d,To[i]=(*pus).id,Fr[i]=now);
if(pus!=G.begin())pus--,A[now]-d-(*pus).w<W[i]&&(W[i]=A[now]-d-(*pus).w,To[i]=(*pus).id,Fr[i]=now);
pus=G.lower_bound((ques){A[now]+d,0});
if(pus!=G.end()) (*pus).w-A[now]-d<W[i]&&(W[i]=(*pus).w-A[now]-d,To[i]=(*pus).id,Fr[i]=now);
if(pus!=G.begin()) pus--,d+A[now]-(*pus).w<W[i]&&(W[i]=d+A[now]-(*pus).w,To[i]=(*pus).id,Fr[i]=now);
}
for(j=0;j<F[i].size();j++) now=F[i][j],G.insert((ques){A[now],now});
}
for(i=1;i<=n;i++){
if(!F[i].size()) continue;/*printf("%d %d %d\n",Fr[i],To[i],W[i]);*/un=Getfa(Fr[i]);wn=Getfa(To[i]);un^wn&&(s.add(un,wn,W[i]),s.add(wn,un,W[i]),cnt--,fa[un]=wn);
}
}dfs(S,0);while(m--) scanf("%d%d",&x,&y),printf("%s\n",Ans[x]<=y?"Yes":"No");
}

浙公网安备 33010602011771号