[CF505E]Mr. Kitayuta vs. Bamboos/[海军国际项目办公室]迷途竹林
Posted StaroForgin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF505E]Mr. Kitayuta vs. Bamboos/[海军国际项目办公室]迷途竹林相关的知识,希望对你有一定的参考价值。
Mr. Kitayuta vs. Bamboos
迷途竹林事实上就是经
T
i
w
A
i
r
O
A
O
\\color{red}{TiwAirOAO}
TiwAirOAO巨佬扩大数据范围强化后的版本。真的是强化了吗
不过做了两遍都不会做的我还是埋了吧
题解
很明显,由于我们每次砍树是让树高从
h
h
h变成
max
(
0
,
h
−
p
)
\\max(0,h-p)
max(0,h−p),每次减少的树高不是固定的,这就很难做了,况且它的树高还是会根据时间增加的。
既然我们已经无法简单地知道我们当前删哪个是最优的,不如考虑倒着来。
很显然,我们可以先二分我们的答案,也就是最后的最高的树高度是多少,看如果是这个高度的话能否达到我们的初始状态。
转化回到初始状态,我们的操作相当于也跟原来倒着来的。
我们可以先将所有树的最终高度都设为
m
i
d
mid
mid,我们每次生长相当于所有树的高度减少
a
i
a_{i}
ai,而每次砍树相当于让我们树的高度加上
p
p
p。
很明显,我们树的高度不可能为负数,所以当我们需要时刻保证我们的树高时时刻刻
⩾
0
\\geqslant 0
⩾0。
而我们最后的树高也是必须
⩾
h
i
\\geqslant h_{i}
⩾hi的,否则我们的答案树高一定更高。
很明显,我们倒退回去的方式肯定可以转化成一种正着砍过来的方式,而如果我们的最终高度
⩾
h
i
\\geqslant h_{i}
⩾hi,那么我们最终高度为
h
i
h_{i}
hi时一定也是有解的。
由于我们过程中需要满足
h
i
⩾
0
h_{i}\\geqslant 0
hi⩾0的要求,所以我们可以每次选择一个会最快变得小于
0
0
0的点,将它的高度加上
p
p
p。最终
⩾
h
i
\\geqslant h_{i}
⩾hi的要求,我们可以在最后时刻,将所有还没有用出的操作全部用出,看能否达到条件。
上面的过程我们可以通过优先队列来维护,但优先队列是
log
\\log
log的,事实上我们完全可以直接记录下来在每个时刻,有哪些位置即将不合法,将之后的操作加上去,再将它放到下一个可能不合法的位置就行了。
时间复杂度很明显的 O ( ( n + m k ) l o g A ) O\\left((n+mk)log\\,A\\right) O((n+mk)logA)。
源码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
const LL INF=0x3f3f3f3f;
const int mo=1e9+7;
const int inv2=499122177;
const int jzm=2333;
const int lim=1e9;
const int zero=10000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-5;
typedef pair<LL,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
int n,m,k,cnt[MAXN];LL p;
struct ming{LL h,a;}s[MAXN];
vector<int>vec[MAXN];
bool check(LL mid){
//printf("check %lld\\n",mid);;
for(int i=1;i<m;i++)vec[i].clear();int summ=0;
for(int i=1;i<=n;i++){cnt[i]=0;LL tmp=mid/s[i].a;if(tmp<m)vec[tmp].pb(i);}
for(int i=1;i<m;i++){
summ+=k;//printf("arrive %d\\n",i);
for(int j=0;j<(int)vec[i].size();j++){
int u=vec[i][j];cnt[u]++;summ--;
if(summ<0||!s[u].a)return 0;
LL tmp=(mid+1ll*cnt[u]*p)/s[u].a;
if(tmp<m)vec[tmp].pb(u);
}
}
summ+=k;
for(int i=1;i<=n;i++)
while(mid+1ll*cnt[i]*p-1ll*m*s[i].a<s[i].h&&summ>=0)
cnt[i]++,summ--;
return summ>=0;
}
signed main(){
read(n);read(m);read(k);read(p);LL maxx=0;
for(int i=1;i<=n;i++)read(s[i].h),read(s[i].a),maxx=max(maxx,s[i].a);
LL l=maxx,r=1e15;while(l<r){LL mid=l+r>>1LL;if(check(mid))r=mid;else l=mid+1LL;}
printf("%lld\\n",l);
return 0;
}
谢谢!!!
以上是关于[CF505E]Mr. Kitayuta vs. Bamboos/[海军国际项目办公室]迷途竹林的主要内容,如果未能解决你的问题,请参考以下文章
CF505D Mr. Kitayuta's Technology 并查集 拓扑排序
[Codeforces 505C]Mr. Kitayuta, the Treasure Hunter
Codeforces Round #286 (Div. 1) D. Mr. Kitayuta's Colorful Graph