A
思路
范围内有个。对于区间,找到最后一个小于的的倍数,即。答案是。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define sf(a) scanf("%lld",&(a));
#define pf(a) printf("%lld\n",(a));
typedef long long ll;
using namespace std;
void solve()
{
ll n,v,l,r;
sf(n)sf(v)sf(l)sf(r)
ll ans=(l-1)/v;
ll tmp=r/v;
r=tmp*v;
cout<<r<<endl;
ans+=(n-r)/v;
pf(ans)
}
int main()
{
int t;
cin>>t;
while(t--)
{
solve();
}
}
B
思路
考虑覆盖第个位置,如果有多种选择,那么选择最靠后的一个必然不会坏于其他的选择,因为这样可以在保证覆盖掉第个位置的前提下尽可能多地覆盖后面的点。定义两个指针分别指向当前未覆盖的最左边的点以及下一步要用的heater贪心即可。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define sf(a) scanf("%lld",&(a));
#define pf(a) printf("%lld\n",(a));
typedef long long ll;
using namespace std;
const int N=1003;
ll n,r,m,ans,cnt,tot;
ll one[N],vis[N],d[N];
void print()
{
rep(i,1,m)
cout<<one[i]<<" ";
cout<<endl;
}
int main()
{
sf(n)sf(r)
--r;
rep(i,1,n)
{
ll tmp;
sf(tmp)
if(tmp==1)
one[++m]=i;
}
int ind=1,cur=1;
one[0]=0x3f3f3f3f;
while(cur<=n)
{
int flag=0;
rep(i,ind,m)
{
if(one[i]-r<=cur)
flag=i;
}
if(flag)
{
++ans;
cur=one[flag]+r+1;
ind=flag+1;
}
else
{
ans=-1;
break;
}
}
pf(ans);
}
C
思路
相当于从第一个元素开始分别向左右延申出新的元素,记录每个元素与第一个元素的距离以及左右延申的最大距离,查询时计算即可。另外要注意从左边开始取右边的元素也有可能更优。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define sf(a) scanf("%lld",&(a));
#define pf(a) printf("%lld\n",(a));
typedef long long ll;
using namespace std;
const int N=2E5+10;
ll t,ldep,rdep;
ll dep[N],dir[N];
int main()
{
sf(t)
rep(i,1,t)
{
string ty;
ll p;
cin>>ty;
sf(p)
if(i==1)
continue;
if(ty[0]=='L')
{
dep[p]=++ldep;
}
else if(ty[0]=='R')
{
dep[p]=++rdep;
dir[p]=1;
}
else
{
if(dir[p])
pf(min(ldep+dep[p],rdep-dep[p]))
else
pf(min(rdep+dep[p],ldep-dep[p]))
}
}
}
D
思路
考虑去掉前个元素,那么使用的箱子数关于是不上升的。因此二分一个位置,将该位置之前的元素全部舍弃之后check一下能不能装开即可。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
const int N=2E5+10;
ll n,m,k;
ll a[N];
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
}
bool check(ll x)
{
ll rem=m,cur=0;
rep(i,x,n)
{
if(cur>=a[i])
cur-=a[i];
else if(rem)
{
cur=k-a[i];
--rem;
}
else
return 0;
}
return 1;
}
int main()
{
In(3,&n,&m,&k);
rep(i,1,n)
In(1,a+i);
ll l=1,r=n;
while(l<r)
{
ll mid=(l+r)>>1;
if(check(mid))
r=mid;
else
l=mid+1;
}
Out(1,n-l+1);
}
E
思路
刚开始与是右端对齐的,因为会不断右移,所以对于中的任何一个,都会与中位置在它右边的对答案产生贡献。因此从右到左线性扫一遍,维护在遇到的个数,在中遇到维护答案即可。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define sf(a) scanf("%lld",&(a));
#define pf(a) printf("%lld\n",(a));
typedef long long ll;
using namespace std;
const int M=998244353;
ll n,m,ans,sum;
string a,b;
ll ksm(ll x,ll k)
{
ll ret=1;
while(k)
{
if(k&1)
ret*=x;
ret%=M;
x*=x;
x%=M;
k>>=1;
}
return ret;
}
int main()
{
sf(n)sf(m)
cin>>a>>b;
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
a=' '+a;
b=' '+b;
rep(i,1,m)
{
if(i<=n && a[i]=='1')
sum+=ksm(2,i-1);
if(b[i]=='1')
ans=(ans+sum)%M;
}
pf(ans)
}
F
思路
考虑只走一层的情况,最优必然是从左上角走到右下角或者反向走。因此先把每一层左上角的点与右下角的点之间的曼哈顿距离维护进答案。
现在考虑层之间的转移。走完一层之后的位置必然是该层的左上角或者右下角,转移时也必然是到下一层的左上角或右下角。设作为从起点开始到走完第层并且在第层的左上角(右下角)停止,需要花费的层之间转移的代价。显然这只关系到两层左上角和右下角的元素,要想最终位于第层的左上角,就要先从第层的左上角或右下角转移到第层的右下角,反之同理。最后取维护答案即可。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
puts("");
}
ll max_(pii x)
{
return max(x.first,x.second);
}
bool cmp_(const pii &x,const pii &y)
{
if(max_(x)==max_(y))
{
if(x.first==y.first)
return x.second>y.second;
return x.first<y.first;
}
return max_(x)<max_(y);
}
ll M_dis(ll _,ll __,ll ___,ll ____)
{
return abs(_-___)+abs(__-____);
}
const ll N=2E5+10;
pii da[N] ;
vector<pii> lev[N];
ll n,ans,cnt;
ll dp[N][2];
void print()
{
rep(i,1,cnt)
Out(1,lev[i].size());
// Out_(2,dp[i][0],dp[i][1]);
}
int main()
{
In(1,&n);
rep(i,1,n)
In(2,&da[i].first,&da[i].second);
sort(da+1,da+n+1,cmp_);
rep(i,1,n)
{
if(max_(da[i])!=max_(da[i-1]))
{
lev[cnt].push_back(da[i-1]);
lev[++cnt].push_back(da[i]);
}
else
ans+=M_dis(da[i].first,da[i].second,da[i-1].first,da[i-1].second);
}
if(max_(da[n])==max_(da[n-1]))
lev[cnt].push_back(da[n]);
rep(i,1,cnt)
rep(j,0,1)
dp[i][j]=LLM;
dp[1][0]=lev[1].back().first+lev[1].back().second;
dp[1][1]=lev[1].front().first+lev[1].front().second;
ll dis00,dis01,dis10,dis11;
rep(i,2,cnt)
{
dis00=M_dis(lev[i-1].front().first,lev[i-1].front().second,lev[i].front().first,lev[i].front().second);
dis01=M_dis(lev[i-1].front().first,lev[i-1].front().second,lev[i].back().first,lev[i].back().second);
dis10=M_dis(lev[i-1].back().first,lev[i-1].back().second,lev[i].front().first,lev[i].front().second);
dis11=M_dis(lev[i-1].back().first,lev[i-1].back().second,lev[i].back().first,lev[i].back().second);
dp[i][0]=min(dp[i-1][0]+dis01,dp[i-1][1]+dis11);
dp[i][1]=min(dp[i-1][0]+dis00,dp[i-1][1]+dis10);
}
Out(1,ans+min(dp[cnt][0],dp[cnt][1]));
}