## whyorwhnt的专栏

One must wait until the evening to see how splendid the day has been

# 第九届北航程序设计大赛网络预赛——水题题解

A BUAA 759 晴天小猪是点赞狂魔

#include <cstdio>

int main ()
{
int T;
scanf("%d",&T);
while (T--)
{
long long n;
scanf("%lld",&n);
long long c=n*(n+1)/2,sum=0;
int k=n+1;
for (long long i=1;i<=n;i++)
{
long long data;
scanf("%lld",&data);
sum+=data*i*(k-i);
}
printf("%.3lf\n",1.0*sum/c);
}
return 0;
}

B BUAA 765 晴天小猪的披萨

#include <cstdio>
#include <cstring>

const int N=505;
bool map[N][N];
bool vis[N];
int match[N];

int n,m,k;

bool Dfs (int u)
{
for (int v=1;v<=m;v++)
if (vis[v] == false && map[u][v])
{
vis[v]=true;
if (match[v]==0 || Dfs(match[v]))
{
match[v]=u;
return true;
}
}
return false;
}

int main ()
{
while (~scanf("%d%d%d",&n,&m,&k))
{
int i,temp1,temp2,sum=0;
memset(map,false,sizeof(map));
memset(match,0,sizeof(match));
for (i=1;i<=k;i++)
{
scanf("%d%d",&temp1,&temp2);
map[temp1][temp2]=true;
}
for (i=1;i<=n;i++)
{
memset(vis,false,sizeof(vis));
if (Dfs(i))
sum++;
}
printf("%d\n",sum);
}
return 0;
}

E BUAA 735 晴天小猪来刷人人

#include <cstdio>
#include <cstring>
#define max(a,b) ((a)>(b)?(a):(b))

const int N=1000005;

int data[N],dis[N];
int poor[N];
int n,m;

int Deal (int k)
{
int left=0,right=k-1,mid,ans;
while (left<=right)
{//二分判定一个空段k，可以利用m次补签，最早可以和什么位置构成连续
mid=(left+right)>>1;
if (poor[k-1]-poor[mid]<=m) //其实是以这一空段的开始为结束，所以用前一段的数据
{
ans=mid;
right=mid-1;
}
else
left=mid+1;
}
return dis[k]-dis[ans]+m;
}

int main ()
{
int T,i;
scanf("%d",&T);
while (T--)
{
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++)
scanf("%d",&data[i]);
data[n+1]=-1;   //
int cnt=0; //不连续的段数
int pre=1;//pre记录上一次开始连续签到(连续1天也算)时的起始位置
for (i=2;i<=n+1;i++)
if (data[i]!=data[i-1]+1)
{
cnt++;
dis[cnt]=i-pre;//记录在连续的这段时间内(不含当天)有多少天不需要补签
poor[cnt]=data[i]-data[i-1]-1;//记录两次之间隔了多少天
pre=i;
}
//       for (i=1;i<=cnt;i++) printf("%d %d\n",dis[i],poor[i]);
if (cnt==1)
{
printf("%d\n",n+m);
continue;
}
for (i=1;i<=cnt;i++)  //前缀和优化
{
dis[i]+=dis[i-1];
poor[i]+=poor[i-1];
}
int ans=0;
for (i=1;i<=cnt;i++)  //枚举每一个空段
ans=max(ans,Deal(i));
printf("%d\n",ans);
}
return 0;
}

F BUAA 747 晴天小猪砌墙

#include <cstdio>
#include <cstring>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))

const int N=1000005;
const int INF=2000000;
int data[N],l[N],r[N];

int main ()
{
int T,n;
scanf("%d",&T);
while (T--)
{
long long sum=0;
int i,left=0,right=0;
scanf("%d",&n);
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
for (i=1;i<=n;i++)
{
scanf("%d",&data[i]);
l[i]=left;
left=max(left,data[i]);
}
for (i=n;i>0;i--)
{
r[i]=right;
right=max(right,data[i]);
}
for (i=1;i<=n;i++)
{
int del=min(l[i],r[i]);
if (del>data[i])
sum+=del-data[i];
}
printf("%lld\n",sum);
}
return 0;
}

I BUAA 732 晴天小猪仰慕上古神犇GG

#include <cstdio>

int Gcd (int x,int y)
{
return !y?x:Gcd(y,x%y);
}

int main ()
{
int T;
scanf("%d",&T);
while (T--)
{
int a,b;
scanf("%d%d",&a,&b);
int x=a*(100-b);
int y=10000-a*b;
int k=Gcd(x,y);
int t=Gcd(y-x,y);
printf("%d/%d %d/%d\n",x/k,y/k,(y-x)/t,y/t);
}
return 0;
}

K BUAA 727 晴天小猪向昂神学习

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define lowbit(x) ((x)&(-(x)))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))

const int N=100005;
int data[N],dis[N];//离散化数组
int tot; //离散化后的数字上限
int dp[N];//dp[i]记录以i为截止，最长连续上升子串的长度
int f[N]; //f[i]记录以i为开始，最长连续上升子串的长度
int bit[N]; //树状数组

void Update (int k,int val)
{
while (k<=tot)  //是<=tot,也即离散化后数字上限
{
bit[k]=max(bit[k],val);
k+=lowbit(k);
}
}

int Cal (int k)
{
int ans=0;
while (k>0)
{
ans=max(ans,bit[k]);
k-=lowbit(k);
}
return ans;
}

int main ()
{
int T;
scanf("%d",&T);
while (T--)
{
int i,n;
scanf("%d",&n);
for (i=1;i<=n;i++)
{
scanf("%d",&data[i]);
dis[i]=data[i];
}
memset(dp,0,sizeof(dp));
memset(f,0,sizeof(f));
memset(bit,0,sizeof(bit));
sort(dis+1,dis+n+1);
tot=unique(dis+1,dis+n+1)-(dis+1);

for (i=1;i<=n;i++)  //离散化
data[i] = lower_bound(dis+1,dis+n+1,data[i])-(dis);
dp[1]=1;
for (i=2;i<=n;i++)
if (data[i]>data[i-1])
dp[i]=dp[i-1]+1;
else
dp[i]=1;
f[n]=1;
for (i=n-1;i>=1;i--)
if (data[i]<data[i+1])
f[i]=f[i+1]+1;
else
f[i]=1;
int ans=0,tmp;
for (i=1;i<=n;i++)
{
tmp=Cal(data[i]-1);
ans=max(ans,tmp+f[i]);
Update(data[i],dp[i]);
}
printf("%d\n",ans);
}
return 0;
}

06-04 115

06-20 101

04-17 590

08-19 813

12-19 1404

06-20 41

05-14 246

07-19 8540

06-16 1258

04-26 836