Codeforces Round #632 (Div. 2)部分题解

A. Little Artem

开局天崩构造题,确实不太会构造题。我的做法是黑白砖块交替出现(黑先),判断最后黑的砖块是比白的多1还是相等,若相等则将最后一行的一个白砖变为黑砖

#include
#define ll long long
#define ull unsigned long long
#define pb push_back
#define lowbit(x) ((x)&(-x))
#define inf 0x3f3f3f3f
#define endl "\n"
#define MP(x,y) (make_pair(x,y))
#define pll pair
#define pi 3.1415926535
using namespace std;
char s[105][105];
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m;
        bool f=1;
        scanf("%d%d",&n,&m);
        int num = 0;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(f) s[i][j]='B',num++;
                else s[i][j]='W',num--;
                f=!f;
            }
            s[i][m]=0;
        }
        if(num==0)
        for(int i=0;i<m;i++){
            if(s[n-1][i]=='W'){
                s[n-1][i]='B';
                break;
            }
        }
        for(int i=0;i<n;i++){
            cout<<s[i]<<endl;
        }
    }
}

B. Kind Anton

注意到题目的条件只能用前面的元素更新后面,故倒过来做看前面是否存在能完成操作的元素

#include
#define ll long long
#define ull unsigned long long
#define pb push_back
#define lowbit(x) ((x)&(-x))
#define inf 0x3f3f3f3f
#define endl "\n"
#define MP(x,y) (make_pair(x,y))
#define pll pair
#define pi 3.1415926535
using namespace std;
int n,a[100005],b[100005];
map<int,int> num;
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        num[0]=0,num[1]=0,num[-1]=0;
        scanf("%d",&n);
        bool f= 1;
        for(int i=0;i<n;i++) scanf("%d",&a[i]),num[a[i]]++;
        for(int i=0;i<n;i++) scanf("%d",&b[i]);
        for(int i=n-1;i>=0;i--){
            num[a[i]]--;
            if(b[i]>a[i] && num[1]==0){
                f=0;
                break;
            }
            if(b[i]<a[i] && num[-1]==0){
                f=0;
                break;
            }
        }
        puts(f?"YES":"NO");
    }

}

C. Eugene and an array

计数题,维护下前缀和,显然前缀和相等的两个位置中间段的和为0,存下每一个元素之前的第一个与他前缀和相等的位置。枚举左端点,找不包含0区间的最大右端点。可以用个set,或者单调栈。

#include
#define ll long long
#define ull unsigned long long
#define pb push_back
#define lowbit(x) ((x)&(-x))
#define inf 0x3f3f3f3f
#define endl "\n"
#define MP(x,y) (make_pair(x,y))
#define pll pair
#define pi 3.1415926535
using namespace std;
int n,a[200005];
ll sum[200005];
map<ll,int> ver;
struct nd{
    int l,r;
}p[200005];
bool cmp(nd x,nd y){
    return x.l<y.l;
}
multiset<int> s;
int tot;
int main(){
    scanf("%d",&n);
    ll ans = 0;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
        if(ver[sum[i]]){
            p[tot].l = ver[sum[i]]+1;
            p[tot].r = i;
            tot++;
            s.insert(i);
        }else if(sum[i]==0){
            p[tot].l = 1;
            p[tot].r = i;
            tot++;
            s.insert(i);
        }
        ver[sum[i]] = i;
    }
    sort(p,p+tot,cmp);
    s.insert(n+1);
    int now = 0;
    for(int i=1;i<=n;i++){
        while(now<tot && p[now].l<i){
            //cout<
            s.erase(s.find(p[now].r));
            now++;
        }
        ans +=(*s.begin()-i);
    }
    cout<<ans<<endl;
}

D. Challenges in school №41

暴力题,先将每一轮最多的操作做完,可以得到最小的轮次数和操作数,操作数即最大的轮次数,加上k在这个区间之外就输出-1,否则用这些操作构造k轮即可。

#include
#define ll long long
#define ull unsigned long long
#define pb push_back
#define lowbit(x) ((x)&(-x))
#define inf 0x3f3f3f3f
#define endl "\n"
#define MP(x,y) (make_pair(x,y))
#define pll pair
#define pi 3.1415926535
using namespace std;
int n,k;
char s[3005];
vector<int> ans[3000005];
int p[3000005];
int main(){
    scanf("%d%d",&n,&k);
    scanf("%s",s+1);
    int num = 0;
    int sum = 0;
    while(1){
        for(int i=1;i<=n;i++){
            if(s[i]=='R' && s[i+1] == 'L'){
                s[i]='L',s[i+1]='R';
                ans[num].pb(i),i++;
                sum++;
            }
        }
        if(ans[num].size()==0)
            break;
        num++;
    }
    if(sum<k || num>k){
        puts("-1");
    }else{
        int x = num;
        for(int i=0;i<num;i++){
            while(ans[i].size()-p[i]>1 && x<k){
                x++;
                printf("1 %d\n",ans[i][p[i]]);
                p[i]++;
            }
            printf("%d",ans[i].size()-p[i]);
            for(int j=p[i];j<ans[i].size();j++){
                printf(" %d",ans[i][j]);
            }
            puts("");
        }
    }
    return 0;
}

E

看傻了,不会构造,再见

F. Kate and imperfection

当时把题读反了,吐血。考虑构造一个大小为k的子集,要是任意两个元素的最大gcd最小,显然优先把1和质数放入集合,把1和这些质数当做基,假设你现在拥有的集合的gcd为m-1,当你加入下一个数后gcd变为m,你可以加入小于等于m的最小质因子的基(1,2,3,5…)*m。然后我们可以这样考虑,当我们加入一个数a后,这个集合的gcd变为了a/(a的最小质因子),故我们将2~n的每个数除以它的最小质因子排序即可。

#include
#define ll long long
#define ull unsigned long long
#define pb push_back
#define lowbit(x) ((x)&(-x))
#define inf 0x3f3f3f3f
#define endl "\n"
#define MP(x,y) (make_pair(x,y))
#define pll pair
#define pi 3.1415926535
using namespace std;
int n;
vector<int> a;
bool v[500005];
int main(){
    scanf("%d",&n);
    for(int i=2;i<=n;i++){
        if(v[i]) continue;
        for(int j=i;j<=n;j+=i){
            if(v[j]) continue;
            a.pb(j/i);
            v[j]=1;
        }
    }
    sort(a.begin(),a.end());
    for(int i=0;i<a.size();i++){
        cout<<a[i]<<' ';
    }
}

你可能感兴趣的:(Codeforces Round #632 (Div. 2)部分题解)