CF803

CF803A

要求字典序最大 那么先填第一行第一列 其次第二行第二列 以此类推

从左往右填 模拟即可

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define inl inline
#define mid (l+r>>1)
const int N=1e2+5;
const int M=2e3+5;
const int mod=1e5+3;
inl int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
inl void write(int x){
    if(x<0){x=-x;putchar('-');}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
inl void writei(int x){write(x);putchar(' ');}
inl void writel(int x){write(x);putchar('\n');}
int n,k,a[N][N];
signed main(){
    n=read();k=read();
    if(k>n*n){puts("-1");return 0;}
    for(int i=1;i<=n;i++){
        if(!k)break;
        a[i][i]=1;k--;
        for(int j=1;i+j<=n;j++){
            if(k<2)break;
            a[i][i+j]=a[i+j][i]=1;k-=2;
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++)
            writei(a[i][j]);
        puts("");
    }
    return 0;
}

CF803B

比较水的B。左右分别扫一遍即可。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define inl inline
const int N=2e5+5;
const int M=2e3+5;
const int inf=0x3f3f3f3f;
inl int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
inl void write(int x){
    if(x<0){x=-x;putchar('-');}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
inl void writei(int x){write(x);putchar(' ');}
inl void writel(int x){write(x);putchar('\n');}
int n,k,a[N],ans[N];
signed main(){
    n=read();
    for(int i=1;i<=n;i++)a[i]=read();
    if(a[1])ans[1]=inf;
    for(int i=2;i<=n;i++)
        if(a[i])ans[i]=ans[i-1]+1;
    for(int i=n-1;i;i--)
        ans[i]=min(ans[i],ans[i+1]+1);
    for(int i=1;i<=n;i++)writei(ans[i]);
    return 0;
}

CF803C

构造。

一个显然的性质:对于一个满足条件的序列 n一定是每个数gcd的倍数

那么可以求出 \(n\) 的所有因数 有单调性可以二分每个数的gcd

考虑怎么check 对于严格上升子序列 和的最小情况就是 \(\dfrac{k\times (k+1)}{2}\)

其余比他大的和都可以构造出来(最后一项直接加即可)

那么满足 \(\dfrac{k\times (k+1)}{2}>\dfrac{n}{mid}\) 就有解

复杂度 \(O(k\log (n的因数个数))\) 这里 \(k\) 一定小于 \(10^5\)
(否则 \(\dfrac{k\times (k+1)}{2}>n\) )

\(k\le 10^{10}\) 懒得特判 直接开 __int128 了(快读快写的方便之处

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define inl inline
#define int __int128
const int N=1e6+5;
const int M=2e3+5;
const int inf=0x3f3f3f3f;
inl int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
inl void write(int x){
    if(x<0){x=-x;putchar('-');}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
inl void writei(int x){write(x);putchar(' ');}
inl void writel(int x){write(x);putchar('\n');}
int n,k,ans[N];
vector<int>v;
inl bool check(int mid){
    int m=n/mid;
    if(k*(k+1)/2>m)return 0;
    for(int i=1;i<=k-1;i++)ans[i]=i*mid,m-=i;
    ans[k]=m*mid;
    return 1;
}
signed main(){
    n=read();k=read();
    for(int i=1;i*i<=n;i++){
        if(n%i)continue;
        v.push_back(i);v.push_back(n/i);
    }
    sort(v.begin(),v.end());
    int l=0,r=v.size()-1;
    while(l<=r){
        int mid=l+r>>1;
        if(check(v[mid]))l=mid+1;
        else r=mid-1;
    }
    if(!ans[1])puts("-1");
    else for(int i=1;i<=k;i++)writei(ans[i]);
    return 0;
}

CF803D

感觉这题做过(?)

把每一小段变成数 那么就是把一个序列分成 \(k\) 段 使每段的最大长度最小

先二分答案 每次考虑加上这个数超不超 \(mid\)

也可以当做每次合并相邻的两个数 直到并成 \(k\)

链表+堆维护 但我懒得写了()

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define inl inline
#define int ll
const int N=1e6+5;
const int M=2e3+5;
const int inf=0x3f3f3f3f;
inl int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
inl void write(int x){
    if(x<0){x=-x;putchar('-');}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
inl void writei(int x){write(x);putchar(' ');}
inl void writel(int x){write(x);putchar('\n');}
int n,k,len,a[N],cnt,ans;
char c;
string s;
inl bool check(int mid){
    int num=1,len=0;
    for(int i=1;i<=cnt;i++){
        if(a[i]>mid)return 0;
        if(len+a[i]>mid)len=a[i],num++;
        else len+=a[i];
    }
    if(num>k)return 0;
    return 1;
}
signed main(){
    k=read();
    while((c=getchar())^'\n')s+=c;
    for(auto i:s){
        if(i==' '||i=='-'){
            a[++cnt]=len+1,len=0;
        }else len++;
    }
    a[++cnt]=len;
    int l=1,r=s.size();
    while(l<=r){
        int mid=l+r>>1;
        if(check(mid))ans=mid,r=mid-1;
        else l=mid+1;
    }
    writel(ans);
    return 0;
}

CF803E

看到大于等于这类东西 想到差分约束

那么设 \(dis_i\) 表示 \([1,i]\) 内W出现次数-L出现次数

那么有以下关系:

\[dis_i-dis_{i-1}=1,s[i]=W \]

\[dis_i-dis_{i-1}=-1,s[i]=L \]

\[dis_i-dis_{i-1}=0,s[i]=D \]

\[-1\le dis_i-dis_{i-1}\le 1,s[i]=? \]

关于 \(k\) 的限制:

\[-(k-1)\le dis_i-dis_0\le k-1,i\le n-1 \]

\[dis_i-dis_0=k\quad or\quad dis_i-dis_0=-k,i=n \]

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define inl inline
#define int ll
const int N=1e6+5;
const int M=2e3+5;
const int inf=0x3f3f3f3f;
inl int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
inl void write(int x){
    if(x<0){x=-x;putchar('-');}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
inl void writei(int x){write(x);putchar(' ');}
inl void writel(int x){write(x);putchar('\n');}
int n,k,len,a[N],ans;
int head[N],to[N],nxt[N],w[N],cntt;
char c;
inl void add(int u,int v,int c){
    nxt[++cntt]=head[u];
    to[cntt]=v;w[cntt]=c;
    head[u]=cntt;
}
int vis[N],dis[N],cnt[N];
inl bool spfa(){
    queue<int>q;
    memset(dis,0x3f,sizeof dis);
    memset(vis,0,sizeof vis);
    memset(cnt,0,sizeof cnt);
    q.push(0);dis[0]=0;
    while(!q.empty()){
        int x=q.front();q.pop();vis[x]=0;
        for(int i=head[x];i;i=nxt[i]){
            int y=to[i],c=w[i];
            if(dis[y]>dis[x]+c){
                dis[y]=dis[x]+c;
                cnt[y]=cnt[x]+1;
                if(cnt[y]>n)return 0;
                if(!vis[y]){q.push(y);vis[y]=1;}
            }
        }
    }
    return 1;
}
signed main(){
    n=read();k=read();
    for(int i=1;i<=n;i++){
        scanf(" %c",&c);
        if(c=='W'){
            add(i,i-1,-1);
            add(i-1,i,1);
        }
        if(c=='L'){
            add(i,i-1,1);
            add(i-1,i,-1);
        }
        if(c=='D'){
            add(i,i-1,0);
            add(i-1,i,0);
        }
        if(c=='?'){
            add(i,i-1,1);
            add(i-1,i,1);
        }
    }
    for(int i=1;i<n;i++){
        add(i,0,k-1);
        add(0,i,k-1);
    }
    add(n,0,-k);
    add(0,n,k);
    if(spfa()){
        for(int i=1;i<=n;i++){
            if(!(dis[i]-dis[i-1]))putchar('D');
            if(dis[i]-dis[i-1]==1)putchar('W');
            if(dis[i]-dis[i-1]==-1)putchar('L');
        }
        return 0;
    }
    head[n]=nxt[head[n]];
    head[0]=nxt[head[0]];
    add(n,0,k);
    add(0,n,-k);
    if(spfa()){
        for(int i=1;i<=n;i++){
            if(!(dis[i]-dis[i-1]))putchar('D');
            if(dis[i]-dis[i-1]==1)putchar('W');
            if(dis[i]-dis[i-1]==-1)putchar('L');
        }
        return 0;
    }
    puts("NO");
    return 0;
}
posted @ 2023-11-01 19:26  xiang_xiang  阅读(304)  评论(0编辑  收藏  举报