Codeforces Round #751 (Div. 1)
CF1601A Array Elimination
分析
可以发现每一位可以拆开,也就是每一位的一的个数一定是 \(k\) 的倍数,
直接求 \(\gcd\) 出来,它的约数就是所有 \(k\) 的取值(\(\gcd=0\)就是 \(1\sim n\))
代码
#include <cstdio>
#include <cctype>
#include <cstring>
using namespace std;
const int N=200011; int n,GCD,a[N];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
int gcd(int x,int y){return y?gcd(y,x%y):x;}
int main(){
for (int T=iut();T;--T){
n=iut(),GCD=0;
for (int i=1;i<=n;++i) a[i]=iut();
for (int i=0;i<30;++i){
int C=0;
for (int j=1;j<=n;++j)
if ((a[j]>>i)&1) ++C;
GCD=gcd(GCD,C);
}
for (int i=1;i<=n;++i)
if (gcd(GCD,i)==i) printf("%d ",i);
putchar(10);
}
return 0;
}
CF1601B Frog Traveler
代码(线段树优化建图跑Dijkstra)
//直接O(n)贪心更好写
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1000011; pair<int,int>heap[N<<1];
struct node{int y,w,next;}e[N*6];
int pre[N],p[N],Cnt,et,n,as[N],cnt,dis[N],b[N],ls[N],rs[N],a[N],root;
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void print(int x){
if (x==n) return; print(pre[x]);
if (x<=n) printf("%d ",p[x]);
}
void add(int x,int y,int w){
e[++et]=(node){y,w,as[x]},as[x]=et;
}
void Push(pair<int,int>w){
heap[++Cnt]=w;
int x=Cnt;
while (x>1){
if (heap[x]<heap[x>>1])
swap(heap[x],heap[x>>1]),x>>=1;
else return;
}
}
void Pop(){
heap[1]=heap[Cnt--];
int x=1;
while ((x<<1)<=Cnt){
int y=x<<1;
if (y<Cnt&&heap[y+1]<heap[y]) ++y;
if (heap[x]>heap[y]) swap(heap[x],heap[y]),x=y;
else return;
}
}
void Dijkstra(int S){
heap[++Cnt]=make_pair(0,S);
for (int i=0;i<=cnt;++i) dis[i]=0x3f3f3f3f; dis[S]=0;
while (Cnt){
int t=heap[1].first,x=heap[1].second;
Pop(); if (t!=dis[x]) continue;
for (int i=as[x];~i;i=e[i].next)
if (dis[e[i].y]>dis[x]+(e[i].w>0)){
dis[e[i].y]=dis[x]+(e[i].w>0),pre[e[i].y]=x,p[e[i].y]=e[i].w;
Push(make_pair(dis[e[i].y],e[i].y));
}
}
}
void build(int &rt,int l,int r){
rt=++cnt;
if (l==r){
add(rt,b[l],l);
return;
}
int mid=(l+r)>>1;
build(ls[rt],l,mid);
build(rs[rt],mid+1,r);
add(rt,ls[rt],0),add(rt,rs[rt],0);
}
void update(int rt,int l,int r,int x,int y,int z){
if (l==x&&r==y){
add(z,rt,0);
return;
}
int mid=(l+r)>>1;
if (y<=mid) update(ls[rt],l,mid,x,y,z);
else if (x>mid) update(rs[rt],mid+1,r,x,y,z);
else update(ls[rt],l,mid,x,mid,z),update(rs[rt],mid+1,r,mid+1,y,z);
}
int main(){
n=iut(),cnt=n,et=0,memset(as,-1,sizeof(as));
for (int i=1;i<=n;++i) a[i]=iut();
for (int i=1;i<=n;++i) b[i]=i+iut();
build(root,0,n);
for (int i=1;i<=n;++i) update(root,0,n,i-a[i],i,i);
Dijkstra(n);
if (dis[0]==0x3f3f3f3f) printf("-1");
else printf("%d\n",dis[0]+1),print(0);
return 0;
}
CF1601C Optimal Insertion
分析
首先 \(b\) 中元素在 \(c\) 中一定是从小到大排列的
所以升序依次填入每个数,用线段树维护 \(a\) 每个位置能提供的逆序对,那肯定越小越好
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
const int N=1000011; long long ans;
int A[N],a[N],b[N],k,n,m,c[N],lazy[N<<2],rk[N];
struct rec{
int p,w;
}w[N<<2];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
bool cmp(int x,int y){return a[x]<a[y];}
rec pup(rec x,rec y){return x.w>y.w?y:x;}
void Update(int x,int y){
for (;x<=k;x+=-x&x) c[x]+=y;
}
int Query(int x){
int ans=0;
for (;x;x-=-x&x) ans+=c[x];
return ans;
}
void ptag(int k,int z){w[k].w+=z,lazy[k]+=z;}
void pdown(int k){
if (lazy[k]){
ptag(k<<1,lazy[k]);
ptag(k<<1|1,lazy[k]);
lazy[k]=0;
}
}
void build(int k,int l,int r){
lazy[k]=0;
if (l==r){
w[k]=(rec){l,0};
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
w[k]=pup(w[k<<1],w[k<<1|1]);
}
void update(int k,int l,int r,int x,int y,int z){
if (l==x&&r==y){
ptag(k,z);
return;
}
int mid=(l+r)>>1; pdown(k);
if (y<=mid) update(k<<1,l,mid,x,y,z);
else if (x>mid) update(k<<1|1,mid+1,r,x,y,z);
else update(k<<1,l,mid,x,mid,z),update(k<<1|1,mid+1,r,mid+1,y,z);
w[k]=pup(w[k<<1],w[k<<1|1]);
}
rec query(int k,int l,int r,int x,int y){
if (l==x&&r==y) return w[k];
int mid=(l+r)>>1; pdown(k);
if (y<=mid) return query(k<<1,l,mid,x,y);
else if (x>mid) return query(k<<1|1,mid+1,r,x,y);
else return pup(query(k<<1,l,mid,x,mid),query(k<<1|1,mid+1,r,mid+1,y));
}
int main(){
for (int T=iut();T;--T){
n=iut(),m=iut(),ans=0;
for (int i=1;i<=n;++i) rk[i]=i,A[i]=a[i]=iut();
for (int i=1;i<=m;++i) b[i]=iut();
sort(b+1,b+1+m),sort(rk+1,rk+1+n,cmp);
build(1,0,n+1);
for (int i=1;i<=n;++i) update(1,0,n+1,i,n+1,1);
for (int l=1,r,j=1,last=0;l<=m;l=r+1){
for (r=l;r<=m&&b[r]==b[l];++r); --r;
for (;j<=n&&a[rk[j]]<b[r];++j)
update(1,0,n+1,rk[j],n+1,-2);
int J=j;
for (;j<=n&&a[rk[j]]==b[r];++j)
update(1,0,n+1,rk[j],n+1,-1);
rec t=query(1,0,n+1,last,n+1);
last=t.p,ans+=(r-l+1ll)*(t.w+J-1);
while (J<j) update(1,0,n+1,rk[J++],n+1,-1);
}
sort(A+1,A+1+n),k=unique(A+1,A+1+n)-A-1;
for (int i=n;i;--i){
a[i]=lower_bound(A+1,A+1+k,a[i])-A;
ans+=Query(a[i]-1),Update(a[i],1);
}
for (int i=1;i<=k;++i) c[i]=0;
printf("%lld\n",ans);
}
return 0;
}
CF1601D Difficult Mountain
分析
先按照 \(\max\{s_i,a_i\}\) 升序排序,再按照 \(s_i\) 升序排序,这样贪心可以证明一定是最优的
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
const int N=500011;
struct rec{int x,y,mx;}a[N];
int n,A,ans;
int iut(){
int ans=0,f=1; char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
int max(int a,int b){return a>b?a:b;}
bool cmp(rec x,rec y){
if (x.mx!=y.mx) return x.mx<y.mx;
return x.x<y.x;
}
int main(){
n=iut(),A=iut();
for (int i=1;i<=n;++i){
a[i]=(rec){iut(),iut(),0};
a[i].mx=max(a[i].x,a[i].y);
}
sort(a+1,a+1+n,cmp);
for (int i=1;i<=n;++i)
if (a[i].x>=A){
A=max(A,a[i].y);
++ans;
}
return !printf("%d",ans);
}
CF1601E Phys Ed Online
分析
可以发现答案与 \([l,l+ki]\) 的最小值有关,这个可以用ST表预处理出来。
那么答案其实与 \(l\bmod k\) 的值有关,考虑分成 \(k\) 种情况处理。
取出来一定是一段单调递减的位置,从右到左用一个单调递增的单调栈维护。
如果将 \([l,r]\) 的最小值位置 \(mn\) 取出来,那么就是 \([l,mn]\) 是单调栈的答案,\((mn,r]\) 是 \(a[mn]\) 的答案。
直接取出相应的位置计算答案即可。
代码
#include <cstdio>
#include <cctype>
#include <vector>
#include <algorithm>
using namespace std;
const int N=300011; typedef long long lll;
struct rec{int l,r,rk;}; vector<rec>K[N]; lll ans[N],dp[N];
int n,Q,k,f[N][19],lg[N],two[19],a[N],b[N],st[N],Top;
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void print(lll ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
int Get(int x,int y){return a[x]>a[y]?y:x;}
int query(int l,int r){
int z=lg[r-l+1];
return Get(f[l][z],f[r-two[z]+1][z]);
}
int main(){
n=iut(),Q=iut(),k=iut(),lg[0]=-1,two[0]=1;
for (int i=1;i<=n;++i) a[i]=iut(),lg[i]=lg[i>>1]+1,f[i][0]=i;
for (int i=1;i<=lg[n];++i) two[i]=two[i-1]<<1;
for (int j=1;j<=lg[n];++j)
for (int i=1;i+two[j]-1<=n;++i)
f[i][j]=Get(f[i][j-1],f[i+two[j-1]][j-1]);
for (int i=1;i<=Q;++i){
int l=iut(),r=iut();
if (l+k>r) ans[i]=a[l];
else K[l%k].push_back((rec){l,r,i});
}
for (int i=0;i<k;++i)
if (!K[i].empty()){
st[Top=1]=n/k+1,b[n/k]=0;
for (int j=i%k;j<=n;j+=k){
if (!j) continue;
b[j/k]=query(j,(j+k>n)?n:(j+k));
}
for (int j=n/k;~j;--j){
while (Top&&a[b[st[Top]]]>=a[b[j]]) --Top;
dp[j]=dp[st[Top]]+1ll*(st[Top]-j)*a[b[j]];
st[++Top]=j;
}
int len=K[i].size();
for (int j=0;j<len;++j){
rec t=K[i][j];
int mn=query(t.l,t.r),T=(t.r-t.l)/k;
if (t.l==mn) ans[t.rk]=(T+1ll)*a[mn];
else{
int L=t.l/k,R=L+(mn-t.l-1)/k;
ans[t.rk]=1ll*(T-(R-L))*a[mn];
ans[t.rk]+=a[t.l]+dp[L]-dp[R];
}
}
}
for (int i=1;i<=Q;++i) print(ans[i]),putchar(10);
return 0;
}
CF1601F Two Sorts
分析
可以发现字典序的第几个很难求,考虑将排列转换成第几个字典序
考虑折半搜索,如果将 \(n\) 的后六位去除,前若干位就是一个关键字,
只要小于 \(\left\lfloor\frac{n}{10^6}\right\rfloor\) 的非零数都能当作关键字
这些关键字后面可以放任意不超过六位的数字,这个预处理出来就可以了。
如果不作为关键字直接暴力就可以了,注意取模很阴间,所以要二分多少个数需要减去模数。
代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int mod=998244353,MOD=1000000007;
typedef long long lll; vector<int>K[7];
lll s[7],siz[7],n,kth; int ans,ten[8],Kth;
void dfs1(int dep,int now){
if (dep==7) return;
int t=(Kth-now+mod)%mod;
K[dep].push_back(t),s[dep]+=t,++Kth;
for (int i=0;i<10;++i)
dfs1(dep+1,now*10+i);
}
void dfs2(int dep,lll now){
if (now>n) return;
if ((now+1)*ten[6]-1<=n&&now*ten[7]>n){
for (int i=0;i<7;++i){
int t=((kth-now*ten[i])%mod+mod)%mod;
int pos=lower_bound(K[i].begin(),K[i].end(),mod-t)-K[i].begin();
ans=(ans+s[i]+t*siz[i]-mod*(siz[i]-pos))%MOD;
}
kth+=Kth;
return;
}
int t=((kth-now)%mod+mod)%mod;
ans=(ans+t)%MOD,++kth;
for (int i=!dep;i<10;++i)
dfs2(dep+1,now*10+i);
}
int main(){
ios::sync_with_stdio(0);
cin>>n,ten[0]=1,dfs1(0,0);
for (int i=1;i<=7;++i) ten[i]=ten[i-1]*10;
for (int i=0;i<7;++i) sort(K[i].begin(),K[i].end()),siz[i]=K[i].size();
dfs2(0,0);
cout<<ans;
return 0;
}
Codeforces Round #751 (Div. 1)的更多相关文章
- Codeforces Round #751 (Div. 2)/CodeForces1602
CodeForces1602 Two Subsequences 解析: 题目大意 给你一个字符串 \(s\).你需要两个非空字符串 \(a\) 和 \(b\) 并且满足下面的条件: 字符串 \(a\) ...
- Codeforces Round #366 (Div. 2) ABC
Codeforces Round #366 (Div. 2) A I hate that I love that I hate it水题 #I hate that I love that I hate ...
- Codeforces Round #354 (Div. 2) ABCD
Codeforces Round #354 (Div. 2) Problems # Name A Nicholas and Permutation standard input/out ...
- Codeforces Round #368 (Div. 2)
直达–>Codeforces Round #368 (Div. 2) A Brain’s Photos 给你一个NxM的矩阵,一个字母代表一种颜色,如果有”C”,”M”,”Y”三种中任意一种就输 ...
- cf之路,1,Codeforces Round #345 (Div. 2)
cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅..... ...
- Codeforces Round #279 (Div. 2) ABCDE
Codeforces Round #279 (Div. 2) 做得我都变绿了! Problems # Name A Team Olympiad standard input/outpu ...
- Codeforces Round #262 (Div. 2) 1003
Codeforces Round #262 (Div. 2) 1003 C. Present time limit per test 2 seconds memory limit per test 2 ...
- Codeforces Round #262 (Div. 2) 1004
Codeforces Round #262 (Div. 2) 1004 D. Little Victor and Set time limit per test 1 second memory lim ...
- Codeforces Round #371 (Div. 1)
A: 题目大意: 在一个multiset中要求支持3种操作: 1.增加一个数 2.删去一个数 3.给出一个01序列,问multiset中有多少这样的数,把它的十进制表示中的奇数改成1,偶数改成0后和给 ...
- Codeforces Round #268 (Div. 2) ABCD
CF469 Codeforces Round #268 (Div. 2) http://codeforces.com/contest/469 开学了,时间少,水题就不写题解了,不水的题也不写这么详细了 ...
随机推荐
- win32 - service的创建
参考这篇教程:Simple Windows Service in C++ 安装service需要在管理员权限下运行cmd,并输入下面的命令行 C:\>sc create "My Sam ...
- Go 中的反射 reflect 介绍和基本使用
一.什么是反射 在计算机科学中,反射(英语:reflection)是指计算机程序在运行时(runtime)可以访问.检测和修改它本身状态或行为的一种能力.用比喻来说,反射就是程序在运行的时候能够&qu ...
- Notepad++找回自动保存缓存内容的文件
在目录C:\Users\Administrator\AppData\Roaming\Notepad++\backup中找到自动保存的缓存文件. 参考Notepad++找回自动保存缓存内容的文件
- Redis居然还有比RDB和AOF更强大的持久化方式?
https://cloud.tencent.com/developer/article/1786055
- Windows 实例如何开放端口
矩池云 Windows 实例相比于 Linux 实例,除了在租用机器的时候自定义端口外,还需要在 Windows防火墙中添加入口规则.接下来将教大家如何设置 Windows 防火墙,启用端口. 租用成 ...
- Redis哨兵(sentinel)
目录 前言 原理 架构图 下载 命令 配置 启动 查看 Sentinel(哨兵)配置 常用命令 Q&A Redis主从配置异常解决:Error condition on socket for ...
- 【Azure 应用服务】记一次Azure Spring Cloud 的部署错误 (az spring-cloud app deploy -g dev -s testdemo -n demo -p ./hellospring-0.0.1-SNAPSHOT.jar --->>> Failed to wait for deployment instances to be ready)
问题描述 使用Azure Spring Cloud服务,在部署时候失败,收到错误消息为: c:\project\hellospring>az spring-cloud app deploy -g ...
- C++11新特性的一些用法举例②
/** C++11 * 默认成员函数 原来C++类中,有6个默认成员函数: 构造函数 析构函数 拷贝构造函数 拷贝赋值重载 取地址重载 const 取地址重载 最后重要的是前4个,后两个用处不大.默认 ...
- 五: Mysql权限管理
# 权限管理 关于MySQL的权限简单的理解就是MySQL允许你做你权力以内的事情,不可以越界.比如只允许你执行SELECT操 作, 那么你就不能执行UPDATE操作.只允许你从某台机器上连接MySQ ...
- 使用 maven 的 `wagon-maven-plugin`插件 快速部署 到不同的 环境
profile 在pom文件中配置 开发和测试环境的 profile信息, <profiles> <profile> <!-- 开发环境 --> <id> ...