先修正一波自己数据结构以及dp上的弱点。
接下来一小周主要补题+打重现赛
------------------------------------------ 持续更新中
CSUST 3034
这是一个二分的题目。首先观察到每行是单调的 ,然后我们先预处理一下整个矩阵的数据范围,L R经行二分。 题目问我们当前矩阵第K大的是哪一个元素,那么我们就二分答案,去check这个mid值 在矩阵里面有多少个数严格比他小。因为矩阵有n行 ,那么很容易可以计算得到这个mid 值在我们枚举的行里面 排第几大,并算一下有多少个数严格比他小。最终我们return 回去这个严格小的值, 如果check(mid)==K 那么我们继续往大的方向二分
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m,k;
ll a,b,c;
ll check(ll x)
{
ll cnt=0;
if(c==0)
{
for(int i=1; i<=n; i++)
{
ll op=a*i*i+b*i;
if(op<x)
{
cnt=cnt+m;
}
}
}
if(c>0)
{
// 递增
for(int i=1; i<=n; i++)
{
ll vel=a*i*i+b*i;
ll pos=(x-vel)/c;// >=
if(pos>0)
{
//cnt=cnt+min(pos,m);
if(pos>m)
{
cnt+=m;
continue;
}
if((x-vel)%c==0)
{
cnt=cnt+pos-1;
}
if((x-vel)%c!=0)
{
cnt=cnt+pos;
}
}
}
}
if(c<0)
{
//
for(int i=1; i<=n; i++)
{
ll vel=a*i*i+b*i;
ll pos=(x-vel)/c;// >=
if(pos<=0)
{
cnt=cnt+m;
continue;
}
if(pos>0)
{
if(pos>m)
{
continue;
}
else
{
cnt=cnt+(m-pos);
}
}
}
}
return cnt;
}
signed main()
{
scanf("%lld%lld%lld%lld%lld%lld",&n,&m,&k,&a,&b,&c);
ll l=1e18;
ll r=-1e18;
for(int i=1; i<=n; i++)
{
if(c>0)
{
l=min(l,a*i*i+b*i+c);
r=max(r,a*i*i+b*i+c*m);
}
else
{
l=min(l,a*i*i+b*i+c*m);
r=max(r,a*i*i+b*i+c);
}
}
ll ans=0;
ll opp=0;
while(l<=r)
{
ll mid=(l+r)/2;
ll rnm=check(mid);
if(rnm<=(n*m-k))
{
l=mid+1;
ans=mid;
}
if(rnm>(n*m-k))
{
r=mid-1;
}
}
printf("%lld",ans);
}
CSUST 3036
emmm水题一个 but题目读不太明白 ,统计下入度出度就OK
CSUST 3037
n 1e3
m 1e4
最短路的一个trick 当访问到的点是 起点+1时 也就是访问到了终点 直接break