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 开学了,时间少,水题就不写题解了,不水的题也不写这么详细了 ...
随机推荐
- 糟糕,CPU100%了!!!
前言 cpu使用率100%问题,是一个让人非常头疼的问题.因为出现这类问题的原因千奇百怪,最关键的是它不是必现的,有可能是系统运行了一段时间之后,在突然的某个时间点出现问题. 今天特地把我和同事,之前 ...
- matplotlib画图中x轴过于密集的解决办法
import matplotlib.ticker as ticker ax.xaxis.set_major_locator(ticker.MultipleLocator(base=10)) # tic ...
- 【LeetCode剑指offer 01】数组中重复的数字、两个栈实现队列
数组中重复的数字 数组中重复的数字 找出数组中重复的数字. 在一个长度为 n 的数组 nums 里的所有数字都在 0-n-1 的范围内.数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数 ...
- Redis灵魂11问
目录 说说redis都有哪些数据类型吧 Redis为什么快呢? 那为什么Redis6.0之后又改用多线程呢? 知道什么是热key吗?热key问题怎么解决? 什么是缓存击穿.缓存穿透.缓存雪崩? 缓存击 ...
- Docker的使用记录
开始 这是第一个尝试在Leanote上面编写文章,我觉得最重要的事情就是能够保证md文件是能够移植的,否则如果这个软件不靠谱的话,我还能把文章移动到别的地方去.所以先写一篇文章看看效果如何,方便不方便 ...
- 为Oracle链接服务器使用分布式事务
1 现象 在SQL Server中创建指向Oracle的链接服务器,SQL语句在事务中向链接服务器插入数据.返回链接服务器无法启动分布式事务的报错. 2 解决 在Windows平台下,SQL Serv ...
- 使用Order By NULL 解决 group by后自动排序,优化Sql性能
使用Order By NULL 解决 group by后自动排序,优化Sql性能 对于 Group by 后的结果,Mysql搜索引擎会将结果按照Group by 的字段按照升序,自动排序,例如: t ...
- Java 常见的两个错误 -------1.栈溢出 java.lang.StackOverflowError 2.堆溢出 java.lang.OutOfMemoryError /OOM
1 package com.bytezero.exception; 2 3 /** 4 * 5 * @Description Error 6 * @author Bytezero·zhenglei! ...
- 深入解析ASP.NET Core MVC的模块化设计[下篇]
ASP.NET Core MVC的"模块化"设计使我们可以构成应用的基本单元Controller定义在任意的模块(程序集)中,并在运行时动态加载和卸载.<设计篇>介绍了 ...
- AP渗透测试学习
1.测试指标 2.测试环境 SDK: Java JDK ,Android SDK 工具: 7zip dex2jar jd-gui apktool activity 劫持工具 3. ...