9.16-CSP-S开小灶5
T1 乌鸦喝水
经过赛后重新思考,我的做法其实并不需要什么吉司机,只需要一棵普通线段树,或者BIT也OK,然后只需要求一下它前后各有多少个大于等于它的数就行,做法是 的
简单来说就是考虑每个位置到底被喝了多少次,因为如果能喝一定喝,那么每个位置被喝的时间一定是从1开始的一段连续时间,于是考虑找到每个位置喝到什么时候不能喝了。 首先求出每个位置最多能被喝多少次,从小到大排序,然后逐个求解其被喝了多少次,将求解转化为判定,假设我们钦定它喝了 轮,那么其后边的位置经历了 轮,对于大于等于它的位置,这 轮一定都被喝了,于是直接乘起来加上就行,对于比它小的位置,他们被喝了多少次都已经完成求解了,于是直接从数据结构里取出来就行,由于我们钦定了 ,在原二分做法下需要将他们的次数对 或 取 ,所以无脑上了吉司机。但是既然我们已经sort了,可以发现,当前我们解决的位置能被喝的次数,一定大于等于比它小的桶最多能喝的次数-1。
为什么是减一?因为可能这个更小的桶在前边,中间还经历了几个小桶,他们把大桶的可用次数消耗了,导致这一轮恰好大桶不能再喝了,但是既然这个小桶能喝到这一轮,那么大桶至少能喝到上一轮,否则小桶也喝不到这一轮。
于是这样我们可以设一个喝到的最大轮数为 的指针, 单调的移动它就行,移动不了的时候 check一下 ,如果可行贡献就是 ,否则就是 , p最多移动m次,每次移动一个log,因为在当前最大值为 ,所以我们取值的时候也不用取min了,写个普通树就行
平衡树是因为我偷懒,实际上离散化一下上BIT就行。
点击查看代码
%:pragma GCC target("avx")
%:pragma GCC optimize(3)
%:pragma GCC optimize(2)
%:pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i)
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define fir first
#define sec second
#define int ll
using namespace std;
const int maxn=1e5+10;
#define gc if(++ip==ie)fread(ip=buf,1,SZ,stdin)
const int SZ=1<<21;char buf[SZ],*ie=buf+SZ,*ip=ie-1;
inline int read(){ gc;while(*ip<'-')gc; bool f=*ip=='-';if(f)gc; int x=*ip&15;gc; while(*ip>'-'){x*=10;x+=*ip&15;gc;} return f ? -x : x; }
int n,m,Lim;
int w[maxn],a[maxn];
int ans;
int val[maxn];
struct FHQ_Treap{
#define lch V[p].l
#define rch V[p].r
struct Vertex{int l,r,key,val,siz;}V[maxn];
int tot,root;
int New(int x){++tot;V[tot].l=V[tot].r=0;V[tot].val=x;V[tot].key=rand();V[tot].siz=1;return tot;}
void Clear(){tot=root=0;}
void Pushup(int p){V[p].siz=V[lch].siz+V[rch].siz+1;}
void Split(int p,int &rtx,int &rty,int x){
if(p==0)return rtx=rty=0,void();
if(x<V[p].val){Split(V[p].l,rtx,V[p].l,x),rty=p,Pushup(rty);return;}
else {Split(V[p].r,V[p].r,rty,x),rtx=p,Pushup(rtx);return;}
}
int Merge(int rtx,int rty){
if(!rtx || !rty )return rtx|rty;
if(V[rtx].key<V[rty].key){V[rtx].r=Merge(V[rtx].r,rty),Pushup(rtx);return rtx;}
else {V[rty].l=Merge(rtx,V[rty].l),Pushup(rty);return rty;}
}
void Insert(int x){
int l=0,r=0;Split(root,l,r,x);
root=Merge(Merge(l,New(x)),r);
}
int Rank(int x){
int l=0,r=0,res=0;
Split(root,l,r,x-1),res=V[r].siz,root=Merge(l,r);
return res;
}
}T;
struct Seg{
int tr[maxn<<2];
void Pushup(int rt){tr[rt]=tr[rt<<1]+tr[rt<<1|1];}
void Modify(int rt,int l,int r,int x,int w){
if(l==r){return tr[rt]=w,void();}
int mid=(l+r)>>1;
if(x<=mid)Modify(rt<<1,l,mid,x,w);
else Modify(rt<<1|1,mid+1,r,x,w);
Pushup(rt);
}
int Query(int rt,int l,int r,int s,int t,int w){
if(t<s)return 0;
if(s<=l && t>=r)return tr[rt];
int mid=(l+r)>>1,res=0;
if(s<=mid)res+=Query(rt<<1,l,mid,s,t,w);
if(t>mid)res+=Query(rt<<1|1,mid+1,r,s,t,w);
return res;
}
}E;
int pre;
int id[maxn];
int L[maxn],R[maxn];
vector<pii>vec;
int last,ts,mx=1;
bool cmp(const int &x,const int &y){if(val[x]==val[y])return x>y;else return val[x]<val[y];}
bool Check(int x,int mid){ return val[x]>(R[x]+1)*(mid-1)+E.Query(1,1,n,x+1,n,mid-1)+L[x]*mid+E.Query(1,1,n,1,x-1,mid);}
void Sol(int x){
if(val[x]!=last){
for(auto it : vec)E.Modify(1,1,n,it.fir,it.sec);
ts+=vec.size();vec.resize(0);
last=val[x];
}
while(mx<m && Check(x,mx+1))++mx;
if(Check(x,mx))vec.push_back(mair(x,mx)),ans+=mx;
else vec.push_back(mair(x,mx-1)),ans+=mx-1;
}
void solve(){
n=read(),m=read(),Lim=read();
Rep(i,1,n)w[i]=read();Rep(i,1,n)a[i]=read(),id[i]=i;
Rep(i,1,n)val[i]=(Lim-w[i])/a[i]+1;//,cerr<<val[i]<<" ";cerr<<"\n";
Rep(i,1,n){ L[i]=T.Rank(val[i]); T.Insert(val[i]); }
T.Clear();
Dwn(i,n,1){ R[i]=T.Rank(val[i]); T.Insert(val[i]); }
sort(id+1,id+n+1,cmp);
Rep(i,1,n)Sol(id[i]);
printf("%lld\n",ans);
}
#undef int
int main (){ return solve(),0; }
T2 kill
奇奇妙妙
点击查看代码
#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i)
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define fir first
#define sec second
#define int ll
using namespace std;
const int maxn=5e3+10;
int n,m,S;
int p[maxn],q[maxn];
bool vis[maxn];
vector<int>L,R;
int Get(int x,int y){return abs(p[x]-q[y])+abs(q[y]-S);}
bool Check(int Lim){
Rep(i,1,m)vis[i]=false;
int ip=1;
for(auto it : L){
while(ip<=m && (vis[ip] || Get(it,ip)>Lim))++ip;
if(ip<=m)vis[ip]=true;
else return false;
}
ip=m;
for(auto it : R){
while(ip>=1 && (vis[ip] || Get(it,ip)>Lim))--ip;
if(ip>=1)vis[ip]=true;
else return false;
}
return true;
}
void solve(){
cin>>n>>m>>S;
Rep(i,1,n)cin>>p[i],(p[i]>=S ? R.push_back(i) : L.push_back(i));Rep(i,1,m)cin>>q[i];
sort(L.begin(),L.end()),sort(R.begin(),R.end()),sort(q+1,q+m+1);
// reverse(R.begin(),R.end());
int l=-1,r=100000000000LL;
while(r-l>1){
int mid=(l+r)>>1;
if(Check(mid))r=mid;
else l=mid;
}
cout<<r<<"\n";
}
#undef int
int main (){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);return solve(),0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现