C D E 这三道题感觉挺好
 
 
 

决定程序是否能通过优化在要求的时间内完成,程序运行时间为t,你可以选择花X天来优化,优化后程序的运行时间为t/(x+1)取上整,花费的时间为程序运行时间加上优化时间

如果程序运行时间小于等于要求时间,那就不需要优化,否则必须优化,假设优化X天,那么总时间就是X+t/(X+1) ,我们的目标事求他的最小值,根据均值不等式

另外均值不等式中等于号成立的条件是x1=x2=....xn

code

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1e4+5;
int main(){
int T;
scanf("%d",&T);
while(T--){
int n,d;
scanf("%d%d",&n,&d);
if(d<=n) puts("YES");
else {
int x=sqrt(d);
int ans=min(ceil(1.0*d/x)+x,ceil(1.0*d/(x+1))+(x+1));
if(ans<=n+1) puts("YES");
else puts("NO");
}
} }
 

 

对式子进行化简即可发现规律 ,偷懒直接贴官方的题解

#include<cstdio>
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
int main(){
int T;
cin>>T;
while(T--){
int a,b;
cin>>a>>b;
ll now=9,cnt=0;
while(now<=b){
now=now*10+9;
cnt++;
}
cout<<1ll*a*cnt<<endl;
}
}
 

  

两种方法,都需要发现一个性质就是一个长度为2*m的非递减序列仅能构造出一个解

所以这道题本质上是找到使用1-n能凑出多少个不同的非递减序列,并且不能重复

法一: 

法二:问题等价于1-n中每一个数有无限个,从中挑出2*m个元素组成一个集合,有多少种选法,答案是

#include<cstdio>
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
const ll P=1e9+7;
ll jc[1100],inv[1100];
ll qpow(ll a,int n){
ll ans=1;
for(;n;n>>=1,a=a*a%P)
if(n&1) ans=ans*a%P;
return ans;
}
int main(){
jc[0]=1;
for(int i=1;i<=1050;i++){
jc[i]=jc[i-1]*i%P;
inv[i]=qpow(jc[i],P-2);
}
inv[0]=1;
int n,m;
cin>>n>>m;
cout<<jc[n+2*m-1]*inv[2*m]%P*inv[n-1]%P<<endl;
}
 

  

先贴一波官方题解

先二分答案,然后将矩阵的每一行压缩成一个m位的二进制 数(如果比X小就赋值为0,否则赋值为1)这样问题就转化为了是否存在两个数异或值为2^m-1

由于n比较大,不能n^2,但是发现可能的二进制数很少,所以我们可以用将可能的二进制数存下来,然后去枚举这些二进制数,复杂度不高了

#include<cstdio>
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
const int dim1=3e5+5;
const int dim2=8;
int a[dim1][dim2];
int n,m;
int ans_l,ans_r;
bool check(int x){
vector<int> mask(1<<m,-1);
for(int i=0;i<n;i++){
int now=0;
for(int j=0;j<m;j++){
if(a[i][j]>=x) now^=1<<j;
}
mask[now]=i;
}
for(int m1=0;m1<1<<m;m1++){
for(int m2=0;m2<1<<m;m2++){
if(mask[m1]!=-1 && mask[m2]!=-1 && (m1|m2)==(1<<m)-1) {
ans_l=mask[m1],ans_r=mask[m2];
return 1;
}
}
}
return false;
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
scanf("%d",&a[i][j]);
int l=1,r=1e9;
while(l<r){
int mid=(l+r+1)/2;
if(check(mid)) l=mid;
else r=mid-1;
}
check(l);
printf("%d %d\n",ans_l+1,ans_r+1); }
 

  

法一 好想但是代码比较复杂

最小值很容易确定,出现过就是1,否则就是其初始位置

对于每一个数来说,他的最大值有两种情况,第一种是他第一次到达队首之前的位置是哪里,这个等价于计数他前面有多少个数比他大,树状数组来解决

第二个就是相邻两次到达队首的时刻,这个就是就是计数两次之间有多少个不同的数,这个用莫队来完成

法二:模拟移动过程,但是需要将队列逆序,这样避免的移动,插入队首的操作可以看做是队尾增加一个数

插入的同时计算并更新最大值

说的比较粗略,具体看官方题解

法一 树状数组+莫队

#include<bits/stdc++.h>

#define X first
#define Y second using namespace std; const int N=3e5+5;
const int tk=550; typedef pair<int,int> pi;
typedef long long ll; int cnt[N],tot; vector<int> pos[N]; int a[N]; void add(int x){
++cnt[x];
if (cnt[x] == 1) ++tot;
} void rem(int x){
if (cnt[x] == 1) --tot;
--cnt[x];
} int f[N]; void upd(int x){
for (int i = x; i >= 0; i = (i & (i + 1)) - 1)
++f[i];
} int get(int x){
int res = 0;
for (int i = x; i < N; i |= i + 1)
res += f[i];
return res;
} int main(){
int n,m;
cin>>n>>m;
for(int i=0;i<m;i++){
scanf("%d",&a[i]);
--a[i];
}
for(int i=0;i<m;i++){
pos[a[i]].push_back(i);
}
vector<pi> qr;
for(int i=0;i<n;i++){
for(int j=1;j<pos[i].size();j++){
qr.push_back(make_pair(pos[i][j-1]+1,pos[i][j]-1));
}
if(!pos[i].empty()) qr.push_back(make_pair(pos[i].back()+1,m-1));
} sort(qr.begin(),qr.end(),[](pi x,pi y){
if(x.X/tk!=y.X/tk) return x.X<y.X;
if((x.X/tk)&1) return x.Y<y.Y;
return x.Y>y.Y;
});
vector<pi> ans(n);
for(int i=0;i<n;i++)
ans[i]={i,i};
for(int i=0;i<m;i++)
ans[a[i]].X=0;
int L=0,R=-1;
for(int i=0;i<(int)qr.size();i++){
int l=qr[i].X,r=qr[i].Y;
if(l>r) continue;
int x=a[qr[i].X-1];
while(L<l) rem(a[L++]);
while(L>l) add(a[--L]);
while(R>r) rem(a[R--]);
while(R<r) add(a[++R]);
ans[x].Y=max(ans[x].Y,tot);
}
for(int i=0;i<m;i++){
if(i==pos[a[i]][0]) {
ans[a[i]].Y=max(ans[a[i]].Y,a[i]+get(a[i]));
upd(a[i]);
}
}
for(int i=0;i<n;i++){
if(pos[i].empty()){
ans[i].Y=max(ans[i].Y,i+get(i));
}
}
for(int i=0;i<n;i++){
printf("%d %d\n",ans[i].X+1,ans[i].Y+1);
}
}

法2 树状数组

#include<bits/stdc++.h>

using namespace std;

const int maxn=6e5+5;

int f[maxn];

void upd(int x,int val){
for(int i=x;i>=0;i=(i&(i+1))-1)
f[i]+=val;
} int get(int x){
int res=0;
for(int i=x;i<maxn;i|=i+1)
res+=f[i];
return res;
} int main(){
int n,m;
scanf("%d%d",&n,&m);
vector<int> mi(n);
iota(mi.begin(),mi.end(),0);
vector<int> mx=mi;
vector<int> a(m);
for(int i=0;i<m;i++)
scanf("%d",&a[i]),--a[i],mi[a[i]]=0;
vector<int> pos(n);
for(int i=0;i<n;i++)
pos[i]=n-i-1;
for(int i=0;i<n;i++)
upd(i,1);
for(int i=0;i<m;i++){
mx[a[i]]=max(mx[a[i]],get(pos[a[i]]+1));
upd(pos[a[i]],-1);
pos[a[i]]=i+n;
upd(pos[a[i]],1);
}
for(int i=0;i<n;i++)
mx[i]=max(mx[i],get(pos[i]+1));
for(int i=0;i<n;i++)
printf("%d %d\n",mi[i]+1,mx[i]+1);
return 0;
}
 

  

Educational Codeforces Round 80 (Rated for Div. 2)(A-E)的更多相关文章

  1. Educational Codeforces Round 80 (Rated for Div. 2)

    A. Deadline 题目链接:https://codeforces.com/contest/1288/problem/A 题意: 给你一个 N 和 D,问是否存在一个 X , 使得 $x+\lce ...

  2. Educational Codeforces Round 80 (Rated for Div. 2)D E

    D枚举子集 题:https://codeforces.com/contest/1288/problem/D题意:给定n个序列,每个序列m个数,求第i个和第j个序列组成b序列,b序列=max(a[i][ ...

  3. Educational Codeforces Round 80 (Rated for Div. 2) E. Messenger Simulator

    可以推出 min[i]要么是i要么是1,当a序列中存在这个数是1 max[i]的话就比较麻烦了 首先对于i来说,如果还没有被提到第一位的话,他的max可由他后面的这部分序列中 j>=i 的不同数 ...

  4. Educational Codeforces Round 80 (Rated for Div. 2)部分题解

    A. Deadline 题目链接 题目大意 给你\(n,d\)两个数,问是否存在\(x\)使得\(x+\frac{d}{x+1}\leq n\),其中\(\frac{d}{x+1}\)向上取整. 解题 ...

  5. Educational Codeforces Round 80 (Rated for Div. 2)E(树状数组,模拟,思维)

    #define HAVE_STRUCT_TIMESPEC #include<bits/stdc++.h> using namespace std; ],mx[],a[],pos[],sum ...

  6. Educational Codeforces Round 80 (Rated for Div. 2)D(二分答案,状压检验)

    这题1<<M为255,可以logN二分答案后,N*M扫一遍表把N行数据转化为一个小于等于255的数字,再255^2检验答案(比扫一遍表复杂度低),复杂度约为N*M*logN #define ...

  7. Educational Codeforces Round 80 (Rated for Div. 2)C(DP)

    #define HAVE_STRUCT_TIMESPEC #include<bits/stdc++.h> using namespace std; ; ][],temp[][]; int ...

  8. Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship Time Limit: 2000 mSec P ...

  9. Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems(动态规划+矩阵快速幂)

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems Time Limit: 3000 mSec P ...

随机推荐

  1. Thread.yield( )方法

    Java线程中的Thread.yield( )方法,译为线程让步.顾名思义,就是说当一个线程使用了这个方法之后,它就会把自己CPU执行的时间让掉,让自己或者其它的线程运行,注意是让自己或者其他线程运行 ...

  2. EF core (code first) 通过自动迁移实现多租户数据分离 :按Schema分离数据

    前言 本文是多租户系列文章的附加操作文章,如果想查看系列中的其他文章请查看下列文章 主线文章 Asp.net core下利用EF core实现从数据实现多租户(1) Asp.net core下利用EF ...

  3. FastDFS 配置文件 tracker.conf

    FastDFS 版本5.05 配置文件分为三部分   控制器:tracker.conf存储器:storage.conf 客户端:client.conf 文件位置:/etc/fdfs 基本配置(基础配置 ...

  4. Angular目录结构

    一. Angular目录结构 e2e:在e2e/下是端到端测试 node_modules:安装的第三方模块都在这,使用npm install安装的1 Src:我们项目的所有文件 { App:组件,以a ...

  5. windows运行shell脚本

    1. 环境变量的理解:快速找到程序并执行,配置在path的目录下有系统环境和用户环境,配置在此的只要目录路径就好,在cmd输入名字就会去此路径找匹配程序执行 2. 将git安装目录下的....\Git ...

  6. 在命令提示符中的有关mysql命令

    -h:当连接MySQL服务器不在同台主机时,填写主机名或IP地址 -u:登录MySQL的用户名 -p:登录MySQL的密码 注意:密码如果写在命令行的时候一定不能有空格.如果使用的系统为linux并且 ...

  7. oracle数据库的启动、关闭、连接

    登陆数据库 方法一: $ sqlplus / as sysdba [oracle@dev /]$ sqlplus / as sysdba SQL*Plus: Release Production on ...

  8. 第三篇 SpringBoot整合log4j2详解

    源代码:https://pan.baidu.com/s/1d1Lwv1gIvVNltIKVWeEseA 提取码:wff0 SpringBoot整合Log4j2步骤: 1.删除spring-boot-s ...

  9. 并发编程之线程池ThreadPoolExecutor

    前言 在我们平时自己写线程的测试demo时,一般都是用new Thread的方式来创建线程.但是,我们知道创建线程对象,就会在内存中开辟空间,而线程中的任务执行完毕之后,就会销毁. 单个线程的话还好, ...

  10. iis添加asp.net网站,访问提示:由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射

    今天在iis服务器配置asp.net网站,遇到一个问题,记录一下: 问题:由于扩展配置问题而无法提供您请求的页面.如果该页面是脚本,请添加处理程序.如果应下载文件,请添加 MIME 映射. Windo ...