CF1041

CF1041A

序列原来一定是延续的,只需考虑中间少了几个即可。

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

CF1041B

先把 \(c,d\) 约分 发现 \(x,y\) 一定是约分后的 \(c,d\) 同乘一个数

那么答案就是满足条件 \(x,y\) 数量取 \(min\)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline 
#define int ll
#define gc getchar
#define pc putchar
const int N=1e7+5;
const int M=1e5+5;
const int inf=0x3f3f3f3f;
const int mod=998244353;
const double eps=1e-8;
inl int read(){
    int x=0,f=1;char c=gc();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
    return x*f;
}
inl void write(int x){
    if(x<0){pc('-');x=-x;}
    if(x>9)write(x/10);
    pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int a,b,c,d;
inl int gcd(int a,int b){return !b?a:gcd(b,a%b);}
signed main(){
    a=read();b=read();c=read();d=read();
    int x=gcd(c,d);
    c/=x,d/=x;
    writel(min(a/c,b/d));
    return 0;
}

CF1041C

一个显然的贪心:每次操作都取最小的 答案一定最优

那么每次二分找大于等于 当前数加 \(k+1\) 的第一个数即可

注意每个数只能找一次 可以用并查集维护 (题解都是 \(vis\) 数组暴力跳 感觉这复杂度不是很对 一个数被跳很多次可能会炸)

理论上每个数只会被二分筛一次 复杂度 \(O(n\log n)\)

(这题评蓝是恶评了吧)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline 
#define gc getchar
#define pc putchar
const int N=2e5+5;
const int M=1e5+5;
const int inf=0x3f3f3f3f;
const int mod=998244353;
const double eps=1e-8;
inl int read(){
    int x=0,f=1;char c=gc();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
    return x*f;
}
inl void write(int x){
    if(x<0){pc('-');x=-x;}
    if(x>9)write(x/10);
    pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,m,k,ans[N],cnt,fa[N];
struct node{
    int x,id;
    friend bool operator<(node a,node b){return a.x<b.x;}
}a[N];
inl int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
signed main(){
    n=read();m=read();k=read();
    for(int i=1;i<=n;i++)a[i]={read(),i};
    for(int i=1;i<=n+1;i++)fa[i]=i;
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++){
        if(ans[a[i].id])continue;cnt++;
        for(int x=a[i].x;x<=m;){
            int t=lower_bound(a+1,a+n+1,(node){x,0})-a;
            t=find(t);
            if(t>n)break;
            ans[a[t].id]=cnt;fa[t]=t+1;
            x=a[t].x+k+1;
        }
    }
    writel(cnt);
    for(int i=1;i<=n;i++)writei(ans[i]);
    return 0;
}

CF1041D

题意相当于给定几条不相交线段 找一段最长区间 使没被线段覆盖的长度 \(=h\)

发现每次从上升气流开头跳一定优 那么 \(l\) 指针维护线段左端

\(r\) 指针尽量往右跑 放在线段右端 最后一部分下降就是 \(h-ans\)

(注意 \(r\) 指针移完 \(h-ans\) 要至少剩1 否则就落地了!!)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline 
#define int ll
#define gc getchar
#define pc putchar
const int N=2e5+5;
const int M=1e5+5;
const int inf=0x7fffffff;
const int mod=998244353;
const double eps=1e-8;
inl int read(){
    int x=0,f=1;char c=gc();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
    return x*f;
}
inl void write(int x){
    if(x<0){pc('-');x=-x;}
    if(x>9)write(x/10);
    pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,h,x1[N],x2[N],ans,res;
signed main(){
    n=read();h=read();
    for(int i=1;i<=n;i++)x1[i]=read(),x2[i]=read();x1[n+1]=x2[n+1]=inf;
    for(int l=1,r=1;l<=n;ans-=x1[l+1]-x2[l],l++){
        while(ans+x1[r+1]-x2[r]<h)ans+=x1[r+1]-x2[r],r++;//这里是小于号!!!
        res=max(res,x2[r]-x1[l]+h-ans);
    }
    writel(res);
    return 0;
}

CF1041E

神奇构造题。

首先不管怎么割 两个最大值一定有一个是 \(n\) 否则无解

我们大胆猜测:有解一定可以写成链的形式

那么把 \(n\) 放在链的最后即可 把另外 \(n-1\) 个数从小到大排序

最小的数一定放在最左面 否则如果它左面有比它大的数 答案一定取不到它

有一样的数就在这个数后面塞一个最小的没出现的数 注意如果这个数比它大是无解的

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline 
#define gc getchar
#define pc putchar
const int N=2e5+5;
const int M=1e5+5;
const int inf=0x7fffffff;
const int mod=998244353;
const double eps=1e-8;
inl int read(){
    int x=0,f=1;char c=gc();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
    return x*f;
}
inl void write(int x){
    if(x<0){pc('-');x=-x;}
    if(x>9)write(x/10);
    pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,a[N],vis[N],x,y,b[N],l=1,cnt,viss[N];
signed main(){
    n=read();
    for(int i=1;i<=n-1;i++){
        x=read();y=read();
        if(x>y)swap(x,y);
        if(y^n){puts("NO");return 0;}
        a[i]=x;vis[x]++;viss[x]=1;
    }
    sort(a+1,a+n);b[n]=n;
    int t=unique(a+1,a+n)-a-1;
    for(int i=1;i<=t;i++){
        b[++cnt]=a[i];vis[a[i]]--;
        while(vis[a[i]]){
            while(viss[l])l++;viss[l]=1;
            if(l>a[i]){puts("NO");return 0;}
            b[++cnt]=l;vis[a[i]]--;
        }
    }
    puts("YES");
    for(int i=1;i<=n-1;i++)
        writei(b[i]),writel(b[i+1]);
    return 0;
}

CF1041F

首先我们会发现:\(y1,y2\) 没有用 只需看特殊点之间的关系即可

考虑枚举反射的每一段长度 \(l\) 和起始点 \(x\)

image

如图 在这种情况下 \(\dfrac{l}{3}\) 一定 比 \(l\)

那么我们会发现 \(l\) 中如果含有除1之外的奇数 一定不优

那么 \(l\) 一定等于 \(2^n\) 那么 \(n\) 只有 \(\log 10^9\) 种 暴力枚举

那么还需要确定开始点

发现要对于一个上面的关键点想产生贡献 要满足 \(a_i-x\equiv0\pmod {2l}\)

下面的关键点要满足 \(b_i-x\equiv l\pmod {2l}\)

对每个点的答案存进 map 最后找map里数量最多的一个即可

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline 
#define gc getchar
#define pc putchar
const int N=2e5+5;
const int M=1e5+5;
const int inf=0x7fffffff;
const int mod=998244353;
const double eps=1e-8;
inl int read(){
    int x=0,f=1;char c=gc();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
    return x*f;
}
inl void write(int x){
    if(x<0){pc('-');x=-x;}
    if(x>9)write(x/10);
    pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,y,m,a[N],b[N],ans;
map<int,int>mp;
signed main(){
    n=read();y=read();
    for(int i=1;i<=n;i++)a[i]=read();
    m=read();y=read();
    for(int i=1;i<=m;i++)b[i]=read();
    for(int i=1;i<=n;i++)mp[a[i]]++;
    for(int i=1;i<=m;i++)mp[b[i]]++;
    for(auto i:mp)ans=max(ans,i.second);
    for(int i=0;(1<<i)<=1e9;i++){
        mp.clear();int l=(1<<i);
        for(int i=1;i<=n;i++)mp[a[i]%(l<<1)]++;
        for(int i=1;i<=m;i++)mp[(b[i]+l)%(l<<1)]++;
        for(auto i:mp)ans=max(ans,i.second);
    }
    writel(ans);
    return 0;
}
posted @ 2023-10-26 16:53  xiang_xiang  阅读(426)  评论(0编辑  收藏  举报