比赛链接:2017 计蒜之道初赛第六场 题解
A:水题
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int d;
scanf("%d",&d);
printf("+-----+\n");
printf("|");
if(d>=20) printf("-");
else printf(" ");
if(d>=90) printf(" 4G|\n");
else if(d>=60) puts(" 3G|");
else puts(" E|");
d-=20;
for(int i=2;i<6;i++)
{
printf("|");
if(d>=20)
{
for(int j=0;j<i;j++) printf("-");
for(int j=i;j<5;j++) printf(" ");
d-=20;
}
else for(int j=0;j<5;j++) printf(" ");
puts("|");
}
printf("+-----+\n");
return 0;
}
B,C:对于每个pair,RMQ一下就行了。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+100;
const int M=2007;
int dp[N][30];
int mm[N],h[N],n,k,x[M],y[M];
int gg=0;
void initRMQ(int n)
{
mm[0]=-1;
for(int i=1;i<=n;i++)
{
mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
dp[i][0]=h[i];
}
for(int j=1;j<=mm[n];j++)
for(int i=1;i+(1<<j)-1<=n;i++)
dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
int rmq(int x,int y)
{
int k=mm[y-x+1];
return min(dp[x][k],dp[y-(1<<k)+1][k]);
}
int main()
{
freopen("in.txt","r",stdin);
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i)
scanf("%d",&h[i]);
initRMQ(n);
int m,ans=0;
scanf("%d",&m);
for(int i=0;i<m;++i)
scanf("%d%d",&x[i],&y[i]);
for(int i=0;i<m;++i)
for(int j=i+1;j<m;++j)
{
int mi=rmq(min(x[i],x[j]),max(x[i],x[j]));
int y1=y[i],y2=y[j],res=0;
if(y1>mi) res+=y1-mi,y1=mi;
if(y2>mi) res+=y2-mi,y2=mi;
res+=abs(y1-y2)+abs(x[i]-x[j]);
if(res<=k) ++ans;
}
printf("%d\n",ans);
return 0;
}
D: 有点类似单调栈的经典题 。
因此从前往后维护一个单调栈。对于每个点,枚举单调栈划分的区间,在每个区间内枚举高度。这样就能找到合法的区间能使其中的点与它组成的pair合法。
复杂度是
O(nh2)
。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+100;
int n,pre[21][N],k,h[N];
vector<int> rm[N];
int main()
{
int t,m,x,y;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i) scanf("%d",&h[i]);
scanf("%d",&m);
for(int i=0;i<m;++i)
{
scanf("%d%d",&x,&y);
++pre[y][x];
rm[x].push_back(y);
}
for(int i=1;i<=20;i++)
for(int j=1;j<=n;j++)
pre[i][j]+=pre[i][j-1];
for(int i=1;i<=n;i++)
sort(rm[i].begin(),rm[i].end());
vector<int> s;
ll ans=0;
for(int i=1;i<=n;++i)
{
for(int j=0;j<rm[i].size();++j)
for(int p=j+1;p<rm[i].size();++p)
if(rm[i][p]-rm[i][j]<=k) ++ans;
else break;
if(s.size())
for(auto &u:rm[i])
{
int l=1;
for(auto r:s)
{
for(int v=1;v<=20;++v)
{
int L=0;
if(u<=h[r]) L=i-k+abs(u-v);
else L=i-k+abs(h[r]-u)+abs(h[r]-v);
if(L>r) continue;
if(L<l) L=l;
ans+=pre[v][r]-pre[v][L-1];
}
l=r+1;
}
}
while(!s.empty()&&h[s.back()]>=h[i]) s.pop_back();
s.push_back(i);
}
cout << ans << endl;
return 0;
}