Educational Codeforces Round 183 (Rated for Div. 2) 补题
C题没看懂题,其实连续序列不一定要求单一字符,可以ab混合,卡了很长时间
原题链接
C 前缀和
void solve(){int n;cin>>n;string s;cin>>s;s=' '+s;vector<int>a(n+1),pre(n+1,0),suf(n+2,0);forr(i,1,n)a[i]=(s[i]=='a'?1:-1);forr(i,1,n)pre[i]=pre[i-1]+a[i];reforr(i,1,n)suf[i]=suf[i+1]+a[i];if(pre[n]==0)return cout<<0<<endl,void();int ans=n;//前后缀匹配 aababab pre[i]=-suf[j]map<int,vector<int>>id;forr(i,1,n){id[suf[i]].push_back(i);}id[0].push_back(n+1);forr(i,0,n){if(id.count(-pre[i])){auto p=upper_bound(id[-pre[i]].begin(),id[-pre[i]].end(),i);if(p!=id[-pre[i]].end())ans=min(ans,*p-i-1);}}if(ans==n)cout<<-1<<endl;else cout<<ans<<endl;
}
D 构造 思维 背包dp
从0≤k≤n(n−1)20 \le k \le \dfrac{n(n-1)}{2}0≤k≤2n(n−1)初见端倪,整个数组都逆序,就会有n(n−1)2\dfrac{n(n-1)}{2}2n(n−1)个(l,r)(l,r)(l,r)数对
把lenlenlen个变顺序 消除len∗(len−1)2len*(len-1)\over 22len∗(len−1)个对
const int N=1e3,C=1e6+10,mod=1e9+7,inf=1e9+10;
int dp[N],re[N];//dp[i] i是不包含逆序的(l,r)对数 j是顺序段的长度,会消除j*(j-1)/2个(l,r)
void init(){//背包dp初始化 forr(i,1,N){dp[i]=inf;forr(j,2,N){if(j*(j-1)/2>i)break;if(dp[i-j*(j-1)/2]+j<=dp[i]){dp[i]=dp[i-j*(j-1)/2]+j;re[i]=j;//re[i] 消除i个(l,r)时 要将re[i]长度转化为正序}}}
}
//一个完全逆序列 有n*(n-1)/2个(l,r)对
//把len个变顺序 消除len*(len-1)/2个对
void solve(){int n,k;cin>>n>>k;int aim=n*(n-1)/2-k;//不包含逆序的l,r //正序一个长len的区间 会消除(len-1)*len/2的(l,r) aim就是要凑出的消除数vector<int>a(n+1);forr(i,1,n)a[i]=n-i+1;forr(i,1,n){int len=re[aim];//凑出aim个不含逆序对l,r 的反转长度if(i+len-1>n)break;reverse(a.begin()+i,a.begin()+i+len);aim-=len*(len-1)/2;i+=len-1;//注意下一步i还会++if(aim<=0)break;}if(aim>0)cout<<0<<endl;else{forr(i,1,n)cout<<a[i]<<' ';cout<<endl;}
}
signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int _=1;init();cin>>_;while (_--){solve();}return 0;
}
E 线段树
有空再补…