日常做散题记录
CodeForces 1675E
题目描述
题解
众所周知,打算法竞赛的有两种人,要么思维要么数据结构
这道题靠思维做码量过于繁琐了,所以我们采用并查集
选择一个在字符串中至少出现一次的字符(从 "a "到 "z").然后在循环中按字母顺序用前一个字符替换字符串中的所有此类字符.例如,用 "b "替换所有 "c",或用 "z "替换所有 "a".
请注意以上描述,利用并查集我们可以将符合上述特征的字符全部挂靠到最小的字符以完成修改
时间复杂度是\(O(n)\),这是可以接受的
示例代码
#include<bits/stdc++.h>
using namespace std;
class UnionFind {
private:
std::vector<int> parent;
int count;
public:
explicit UnionFind(int n) : parent(1+n), count(n) {
for (int i = 0; i < n; ++i) parent[i] = i;
}
int find(int x) {
if (parent[x] != x) parent[x] = find(parent[x]);
return parent[x];
}
void unite(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX != rootY) {
parent[rootY] = rootX;
--count;
}
}
bool connected(int x, int y) {
return find(x) == find(y);
}
int getCount() const {
return count;
}
};
void solve(){
UnionFind uf(26);
int n,k;cin>>n>>k;
string s;cin>>s;
for(auto c:s){
int x=c-'a';
while(k>0&&uf.find(x)>0){
uf.unite(uf.find(x)-1,x);
k--;
}
}
for(auto c:s){
cout<<(char)(uf.find(c-'a')+'a');
}
cout<<endl;
}
int main(){
int t;
cin>>t;
while(t--)
solve();
}
Codeforces 1977B
题目描述
题解
这道题诈一看可能就是简单的二进制取位的题目,but
不存在一个索引\(0≤i≤n−2\),同时存在 \(a_i≠0\)和\(a_{i+1}≠0\).
请注意以上条件,这句话是这道题需要思考如何优化的点.那么我们如何优化呢??
注意在二进制数中,例如\((1111)_2\),对于这道题所接受的写法,我们可以改写为\((1000-1)\)(在二进制中\((1111)_2+1==(10000)_2\),要想恢复原样我们直接再减回去就ok了$)
根据这个思路,我们可以得到以下结论
\((00111100)_2=(01000-100)_2\)(换句话说就是一个二进制数中一串连续的\(1\)==最高一位加一与原数的最后一位减一即可)
这样我们总是能构造出符合要求的数组
时间复杂度是\(O(log_2 N)\),\(N\)是原数,由于\(N\)最大到\(2^{30}\),对其取以二为底的对数为\(30\),这样是可行的
示例代码
#include<bits/stdc++.h>
using namespace std;
void solve(){
long long x;
cin>>x;
assert(0 <= x && x < (1 << 30));
vector<int> a(32,0);
for(int i = 0;i < 32;++i) {
a[i] = (x >> i) & 1;
}
vector<int> result(33,0);
for(int i=0;i<a.size();i++){
if(i>0){
if(result[i-1]==1&&a[i]==1){
int j=i+1;
while(j<32&&a[j]==1){
j++;
}
result[i-1]=-1;
result[j]=1;
i=j;
}
else{
result[i]=a[i];
}
}
else{
result[i]=a[i];
}
}
cout <<32<< endl;
for(int i = 0;i < 32;++i) {
cout<<result[i]<<' ';
}
cout<<endl;
}
int main(){
int t;cin>>t;
while(t--)
solve();
}
Codeforces 2111 D
题目描述
题解
对于这道题我们首先要明白一点,就是说我们分配教室的时候要让每一组的教室楼层的变化量尽量大,所以我们可以先对教室所在的id从小到大进行排序
之后注意\(n\)的数量的奇偶性.观察题目可知每两节课,不同的组可以交替使用相同同一间教室,按照这个规律为结果赋值就行了
时间复杂度是\(O(6*n/2)\)(其中\(n/2\)向下取整),可以接受
示例代码
#include<bits/stdc++.h>
using namespace std;
void solve(){
int n,m;
cin>>n>>m;
vector<long long> a(m);
for(int i=0;i<m;i++){
cin>>a[i];
}
sort(a.begin(),a.end());
vector<vector<int>> ans(n,vector<int>(6));
for(int i=0;i<n;i+=2){
if(i==n-1){
for(int j=0;j<6;j++){
if(j%2==0)
ans[i][j]=a[i/2];
else
ans[i][j]=a[m-i/2-1];
}
}
else{
for(int j=0;j<6;j++){
if(j%2==0){
ans[i][j]=a[i/2];
ans[i+1][j]=a[m-i/2-1];
}
else{
ans[i][j]=a[m-i/2-1];
ans[i+1][j]=a[i/2];
}
}
}
}
for(int i=0;i<n;i++){
for(int j=0;j<6;j++){
cout<<ans[i][j]<<' ';
}
cout<<endl;
}
cout<<endl;
}
int main(){
ciallo;
ciallo1;
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}
Codeforces 1909 C
题目描述
题解
示例代码
#include<bits/stdc++.h>
using namespace std;
void solve(){
int n;
cin>>n;
vector<pair<long long int,int>> ab;
for(int i=0;i<n;i++){
int l;
cin>>l;
ab.push_back({l,1});
}
for(int i=0;i<n;i++){
int r;
cin>>r;
ab.push_back({r,-1});
}
vector<long long int> c(n);
for(int i=0;i<n;i++){
cin>>c[i];
}
sort(c.begin(),c.end());
sort(ab.begin(),ab.end());
stack<long long int> handle;
vector<long long int> len;
for(int i=0;i<2*n;i++){
if(ab[i].second==1){
handle.push(ab[i].first);
}
else{
if(handle.empty()){
break;
}
len.push_back(ab[i].first-handle.top());
handle.pop();
}
}
sort(len.begin(),len.end());
reverse(len.begin(),len.end());
long long ans=0;
for(int i=0;i<n;i++){
ans+=len[i]*c[i];
}
cout<<ans<<endl;
}
int main(){
ciallo;
ciallo1;
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}

浙公网安备 33010602011771号