[Codeforces Round #542 (Div. 1)] B,C,D,E
- B
第一个是 -1 ,然后随便构造
#include<bits/stdc++.h>
using namespace std;
const int N=2010;
int sub,n;
int a[N];
int main()
{
scanf("%d",&sub);
a[1]=-1;
for(int l=1;l<N;l++){
if(l*1000000>=sub+(l+1)){
n=l+1;break;
}
}
sub+=n;
printf("%d\n",n);
for(int i=1;i<=n;i++){
if(i==1)a[i]=-1;
else a[i]=min(sub,1000000);
if(i>1)sub-=a[i];
}
for(int i=n;i>1;i--){
if(a[i]){
a[i]-=min(sub,a[i]-1);
sub-=min(sub,a[i]-1);
}
if(!a[i]){
a[i]++;
sub++;
}
}
for(int i=1;i<=n;i++)printf("%d ",a[i]);puts("");
}
- C
后缀自动机然后dp一下,每次把新的子串的dp值加上去
#include<bits/stdc++.h>
using namespace std;
const int N=4010;
int a[N*2];
int n;
const int mod=1e9+7;
struct SAM{
struct node{
int len,ch[2],right,par;
}t[N*3];
int cnt,root,tail;
inline int newnode(int _len){
++cnt;t[cnt].len=_len;return cnt;
}
inline void init(){
root=tail=newnode(0);
}
inline int extend(int c){
int np=newnode(t[tail].len+1),p=tail;
while(p&&!t[p].ch[c])t[p].ch[c]=np,p=t[p].par;
if(p==0)t[np].par=root;
else if(t[t[p].ch[c]].len==t[p].len+1)t[np].par=t[p].ch[c];
else {
int nq=newnode(t[p].len+1),q=t[p].ch[c];
memcpy(t[nq].ch,t[q].ch,sizeof(t[q].ch));t[nq].par=t[q].par;
t[q].par=t[np].par=nq;
while(p&&t[p].ch[c]==q)t[p].ch[c]=nq,p=t[p].par;
}
t[np].right=1,tail=np;
return t[t[np].par].len+1;
}
}sam;
int minlen[N];
int f[N][N];
bool judge(int l,int r){
if(r-l+1<4)return 1;
if(r-l+1>4)return 0;
int tmp=a[l]+a[l+1]*2+a[l+2]*4+a[l+3]*8;
if(tmp==12||tmp==15||tmp==10||tmp==7)return false;
return true;
}
int main()
{
scanf("%d",&n);
sam.init();
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
minlen[i]=sam.extend(a[i]);
// cout<<"::"<<minlen[i]<<endl;
}
for(int i=1;i<=n;i++){
f[i][i-1]=1;
for(int j=i;j<=n;j++){
for(int k=j-1;k>=max(i-1,j-4);k--)if(judge(k+1,j)){
f[i][j]+=f[i][k];
f[i][j]%=mod;
}
}
}
// cout<<f[1][3]<<"!"<<endl;
int ans=0;
for(int i=1;i<=n;i++){
int R=i-minlen[i]+1;
for(int j=1;j<=R;j++)ans=(ans+f[j][i])%mod;
printf("%d\n",ans);
}
}
- D
记下pre了之后每次会修改两个区间的值,一个+1,一个-1,我们需要查询一个区间的值。
这个可以分块维护,就可以dp了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
inline int add(int a,int b){a+=b;return a>=mod?a-mod:a;}
inline int sub(int a,int b){a-=b;return a<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline int qpow(int a,int b){int ret=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;}
/*math*/
const int N=1e5+5;
const int BLK=400;
int n,qk,K;
int pre[N],lst[N],cnt[N],_tmp[N];
int tag[BLK],l[BLK],r[BLK],sum[BLK][N],ans[BLK];
int bl[N],f[N],dp[N],a[N];
inline void rebuild(int x){
for(int k=l[x];k<=r[x];k++)sum[x][f[k]]=0;
for(int k=l[x];k<=r[x];k++)f[k]+=tag[x];
tag[x]=0;ans[x]=0;
for(int k=l[x];k<=r[x];k++){
sum[x][f[k]]=add(sum[x][f[k]],dp[k]);
ans[x]=add(ans[x],f[k]<=qk?dp[k]:0);
}
}
inline void upd(int x,int fff,int del=true){
int b=bl[x];
if(del){
sum[b][f[x]]=sub(sum[b][f[x]],dp[x]);
if(f[x]<=qk)ans[b]=sub(ans[b],dp[x]);
}
f[x]+=fff;
sum[b][f[x]]=add(sum[b][f[x]],dp[x]);
if(f[x]<=qk)ans[b]=add(ans[b],dp[x]);
}
inline void ADD(int L,int R,int f){
if(bl[L]==bl[R]){
rebuild(bl[L]);
for(int k=L;k<=R;k++){
upd(k,f);
}
return ;
}
rebuild(bl[L]);
for(int k=L;k<=r[bl[L]];k++)upd(k,f);
for(int k=bl[L]+1;k<=bl[R]-1;k++){
if(f==1){
int tk=qk-tag[k];
ans[k]=sub(ans[k],sum[k][tk]);
++tag[k];
}else{
--tag[k];
int tk=qk-tag[k];
ans[k]=add(ans[k],sum[k][tk]);
}
}
rebuild(bl[R]);
for(int k=l[bl[R]];k<=R;k++)upd(k,f);
}
inline int query(int x){
int res=_tmp[x]+dp[x];
for(int k=1;k<=bl[x]-1;k++)res=add(res,ans[k]);
for(int k=l[bl[x]];k<x;k++)res=add(res,f[k]<=qk?dp[k]:0);
return res;
}
int main()
{
scanf("%d%d",&n,&qk);K=sqrt(n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
pre[i]=lst[a[i]];lst[a[i]]=i;
}
for(int i=1;i<=n;i++){
bl[i]=(i-1)/K+1;
r[bl[i]]=max(r[bl[i]],i);
if(!l[bl[i]])l[bl[i]]=i;
}
dp[1]=1;
for(int i=1;i<=n;i++){
if(i!=1&&pre[i]+1!=i){
ADD(pre[i]+1,i-1,1);
}
if(pre[i])ADD(pre[pre[i]]+1,pre[i],-1);
dp[i+1]=query(i);
rebuild(bl[i]);
upd(i,1);
}
cout<<dp[n+1]<<endl;
}
- E
首先查询1,tot,i可以查1为根时i的size。然后我们按照size排序之后每次二分找没找到fa的点,以此确定一个fa。
就能在规定次数内做出来了。
#include<bits/stdc++.h>
using namespace std;
typedef vector<int> vec;
int query(vector<int> A,int sza,vector<int> B,int szb,int T){
printf("%d\n",sza);
for(int i=0;i<sza;i++)printf("%d ",A[i]);puts("");
printf("%d\n",szb);
for(int i=0;i<szb;i++)printf("%d ",B[i]);puts("");
printf("%d\n",T);
fflush(stdout);
int ans=0;scanf("%d",&ans);
return ans;
}
const int N=510;
int n;
vec t;vec node;
int del[N];int sz[N];
bool cmp(const int a,const int b){return sz[a]>sz[b];}
struct edge{
int u,v;
edge(int u=0,int v=0):u(u),v(v){}
}e[N];int cnt=0;
int qry(int l,int r,int id){
vector<int>Q;
Q.resize(0);
for(int i=l;i<=r;i++)if(!del[node[i]]){
Q.push_back(node[i]);
}
if(Q.size()==0)return 0;
return query((vector<int>){1,1},1,Q,Q.size(),id);
}
int main()
{
scanf("%d",&n);
for(int i=2;i<=n;++i){
t.push_back(i);
}
sz[1]=n;
node.push_back(1);
for(int i=2;i<=n;i++){
sz[i]=query((vector<int>){1,1},1,t,n-1,i);
node.push_back(i);
// cout<<i<<","<<sz[i]<<endl;
}
// puts("----");
sort(node.begin(),node.end(),cmp);
for(int i=n-1;~i;i--){
int x=node[i];
// cout<<x<<" "<<sz[x]<<"::"<<endl;
sz[x]--;
if(sz[x]==0)continue;
while(qry(i+1,n-1,x)){
int l=i+1,r=n-1;
while(l<r){
int mid=(l+r)>>1;
int ret=qry(i+1,mid,x);
if(ret==0){
l=mid+1;
}else{
r=mid;
}
}
e[++cnt]=edge(x,node[l]);
sz[x]--;del[node[l]]=1;
}
}
puts("ANSWER");
for(int i=1;i<=cnt;i++)cout<<e[i].u<<" "<<e[i].v<<endl;
}