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\)
如图 在这种情况下 \(\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;
}