CSP-S加赛0916
下发文件和题解
T1 乌鸦喝水
内存限制:128 MiB
时间限制:2000 ms
标准输入输出
题目类型:传统
评测方式:文本比较
题目描述
输入格式
输出格式
样例
数据范围与提示
感谢巨佬的悉心指导
首先没有人会不去把深度换成次数. 注意是水缸口到水面距离小于{等于}乌鸦能够得着的深度. 因为这个我调了120分钟.
发现乌鸦在前面有水时一定会先喝前面的水,所以这玩意是单调的. 一口剩余次数少的缸必定要先比剩余次数多的缸剩余次数先达到0. 所以把这些缸按照剩余次数从小到大排序,没有剩余次数的删去即可.
枚举每一口缸,把轮数一直增加直到它没水了. 二分这个最后一个让它没水的缸,作为下一口缸枚举的起始点. 在最后的时候,更新答案到这一口缸的剩余次数. 注意轮数超了直接跳出即可.
调试语句就不删了,见证我把每一个部分都调了一遍 精疲力竭了x_x
#include<bits/stdc++.h>
#define ll long long
#define rg register
#define rll rg ll
#define ld double
#define maxn 100001
#define mod 1000000007
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
static inline ll read()
{
rll f=0,x=0;rg char ch=getchar();
while(ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
while(ch>='0'&&ch<='9') x=((x<<3))+((x<<1))+(ch^'0'),ch=getchar();
return f?-x:x;
}
static inline void write(rll x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);putchar(x%10|'0');
}
template<typename T,size_t siz>
class bit
{
#define lowbit(x) (x&-x)
private:
T c[siz];
public:
inline void upd(rg T x,rg T n,rg T v) { for(rg T i=x;i<=n;i+=lowbit(i)) c[i]+=v; }
inline T query(rg T x) { rg T ans=0;for(rg T i=x;i;i-=lowbit(i)) ans+=c[i];return ans; }
#undef lowbit
};
struct node
{
ll a,id;
inline friend bool operator<(rg node a,rg node b) { return a.a<b.a; }
}b[maxn];
ll n,m,x,st,st1,lun=1,tot,ans;
bit<ll,maxn> t;
static inline bool chk(rll x,rll i) { return t.query(x)-t.query(st)<=b[i].a-ans; }
int main()
{
n=read();m=read();x=read();
for(rll i=1;i<=n;i++) b[i].a=x-read();for(rll i=1;i<=n;i++) b[i].a=b[i].a/read()+1;
for(rll i=1;i<=n;i++) if(b[i].a&&!(b[i].a&LLONG_MIN)) b[++tot].a=b[i].a,b[tot].id=tot;
n=tot;sort(b+1,b+n+1);for(rll i=1;i<=n;i++) t.upd(i,n,1);// ,write(b[i].a),put_;putn;
for(rll i=1;i<=n;i++)
{
if(b[i].a-ans<0) { t.upd(b[i].id,n,-1); continue; }
while(lun<=m&&b[i].a-ans>=t.query(n)-t.query(st)) lun++,ans+=t.query(n)-t.query(st),st=0;// ,write(lun),put_;
// write(i);put_;write(lun);putn;
if(lun>m) break;
rll l=st,r=n,mid;while(l<=r) mid=(l+r)>>1,(chk(mid,i)?(st1=mid,l=mid+1):r=mid-1);// ,write(l),put_,write(r),putn;
ans=b[i].a;st=st1;/*putn;write(b[i].id);put_;write(n);putn;*/t.upd(b[i].id,n,-1);
}
write(ans);
return 0;
}
T2 kill
内存限制:256 MiB
时间限制:1000 ms
标准输入输出
题目类型:传统
评测方式:文本比较
暴力贪心,可以发现最优情况一定是选择一个连续段. 这里我困惑了半天,其实可以模拟一下 s 点在左、中、右三种情况,发现选连续段一定是最优的. 所以枚举 n 和 m 即可. 复杂度 O(nm).
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define rg register
#define rll rg ll
#define maxn 100001
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
static inline ll read()
{
rll f=0,x=0;rg char ch=getchar();
while(ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
while(ch>='0'&&ch<='9') x=((x<<3))+((x<<1))+(ch^'0'),ch=getchar();
return f?-x:x;
}
static inline void write(rll x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);putchar(x%10|'0');
}
ll n,m,s,p[maxn],q[maxn],ans=LLONG_MAX;
int main()
{
n=read();m=read();s=read();
for(rll i=1;i<=n;i++) p[i]=read(); for(rll i=1;i<=m;i++) q[i]=read();
sort(q+1,q+m+1);sort(p+1,p+n+1);
for(rll j=1;j<=m-n+1;j++)
{
rll k=0;
for(rll i=1;i<=n;i++)
k=max(k,abs(p[i]-q[j+i-1])+abs(q[j+i-1]-s));
ans=min(ans,k);
}
write(ans);
return 0;
}
--END--
我的博客: 𝟷𝙻𝚒𝚞
本文链接: https://www.cnblogs.com/1Liu/p/16701283.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!