11.1 解题报告
T1
用时:
期望得分:
实际得分:
直接二分,然后贪心 check 一下就行。
#include<bits/stdc++.h>
#define ll long long
#define int long long
//#define ull unsigned long long
#define lc(k) k<<1
#define rc(k) k<<1|1
#define lb lower_bound
#define orz cout<<"gzn ak ioi\n"
const int MAX=1e6+10;
const int MOD=1e9+7;
using namespace std;
inline char readchar() {
static char buf[100000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
#define readchar getchar
int res = 0, f = 0;
char ch = readchar();
for(; !isdigit(ch); ch = readchar()) if(ch == '-') f = 1;
for(; isdigit(ch);ch = readchar()) res = (res << 1) + (res << 3) + (ch ^ '0');
return f ? -res : res;
}
inline void write(int x) {
if(x<0){putchar('-');x=-x;}
if(x>9) write(x/10);
putchar(x%10+'0');
}
/*
一眼二分
让当前数尽量小,这样可以给后面更多的调整空间
*/
int a[MAX],n;
bool check(int lim){
int t=a[1]-lim;
for(int i=2;i<=n;i++){
int x=t+1;
if(x-a[i]>lim) return 0;
t=max(x,a[i]-lim);
}
return 1;
}
signed main(){
// freopen("sequence.in","r",stdin);
// freopen("sequence.out","w",stdout);
n=read();
for(int i=1;i<=n;i++) a[i]=read();
int l=0,r=2e9,ans=0;
while(l<=r){
int mid=(l+r)>>1;
// cout<<mid<<endl;
if(check(mid)) r=mid-1,ans=mid;
else l=mid+1;
}
cout<<ans;
return 0;
}
T2
考场用时:
期望得分:
实际得分:
这题构思+读题花了约
这题就是二分
#include<bits/stdc++.h>
#define ll long long
#define int long long
//#define ull unsigned long long
#define lc(k) k<<1
#define rc(k) k<<1|1
#define lb lower_bound
#define orz cout<<"gzn ak ioi\n"
const int MAX=1e6+10;
const int MOD=1e9+7;
using namespace std;
inline char readchar() {
static char buf[100000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
#define readchar getchar
int res = 0, f = 0;
char ch = readchar();
for(; !isdigit(ch); ch = readchar()) if(ch == '-') f = 1;
for(; isdigit(ch);ch = readchar()) res = (res << 1) + (res << 3) + (ch ^ '0');
return f ? -res : res;
}
inline void write(int x) {
if(x<0){putchar('-');x=-x;}
if(x>9) write(x/10);
putchar(x%10+'0');
}
/*
二分ans,对于check,枚举最终选择的颜色段
对于每个颜色开一个vector,s[i]代表颜色为i的点的所有下标,枚举时只在对应vector内枚举
断环为链,线性的枚举这个长度为lim的区间,O(1)转移dis和
判断dis和是否<=k,满足则直接返回1
假设所有颜色个数都相等,复杂度 O(nlogn)
期望得分100pts
*/
int n,m,k,tong[MAX],cnt;
vector<int> s[MAX];
int del(int i,int l,int r,int mid){
int dell=(s[i][mid]-s[i][mid-1]-1)*(mid-l);
int delr=(s[i][mid]-s[i][mid-1]-1)*(r-mid+1);
return dell-delr;
}
bool check(int lim){
// cout<<lim<<endl;
for(int i=1;i<=cnt;i++){
// cout<<i<<endl;
int siz=s[i].size();
if(siz<2*lim) continue;
int mid=0,sum=0;
for(int j=0;j<lim;j++)
sum+=(s[i][j]-s[i][0]-j);
// cout<<sum<<endl;
while(del(i,0,lim-1,mid+1)<=0){
sum+=del(i,0,lim-1,mid+1);
mid++;
}
// cout<<mid<<" "<<sum<<endl;
if(sum<=k) return 1;
//中点单增
for(int l=1;l+lim-1<siz;l++){
int r=l+lim-1;
sum-=(s[i][mid]-s[i][l-1]-(mid-(l-1)));
sum+=(s[i][r]-s[i][mid]-(r-mid));
while(del(i,l,r,mid+1)<=0){
sum+=del(i,l,r,mid+1);
mid++;
}
// cout<<mid<<" "<<sum<<endl;
if(sum<=k) return 1;
}
}
return 0;
}
signed main(){
// freopen("10.in","r",stdin);
// freopen("magic.out","w",stdout);
n=read(),m=read(),k=read();
// if(n==10&&m==10&&k==1) return puts("3"),0;
for(int i=1;i<=n;i++){
int x=read();
if(!tong[x]) tong[x]=++cnt;
s[tong[x]].push_back(i);
}
for(int i=1;i<=cnt;i++)
for(int j=0,siz=s[i].size();j<siz;j++)
s[i].push_back(n+s[i][j]);
int l=1,r=n,ans=0;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid)) ans=mid,l=mid+1;
else r=mid-1;
// puts("---------------");
}
cout<<ans;
return 0;
}
T3
考场用时:
期望得分:
实际得分:
T2花了太长时间,导致这题暴力都没写,直接
代码没写完。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!