CF803
要求字典序最大 那么先填第一行第一列 其次第二行第二列 以此类推
从左往右填 模拟即可
点击查看代码
#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;
}
比较水的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;
}
构造。
一个显然的性质:对于一个满足条件的序列 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;
}
感觉这题做过(?)
把每一小段变成数 那么就是把一个序列分成 \(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;
}
看到大于等于这类东西 想到差分约束
那么设 \(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;
}