这场小白月赛打的也太爽了吧。三个线段树的题

地址链接:​​https://ac.nowcoder.com/acm/contest/949#question​

人均5题,那我就随便讲讲了

A题  小石的签到题 通过简单的枚举知道 当n=1 小石就输了,输出yang,其他小石均会赢,我枚举到8发现的规律。

/*¼ò»¯°æ*/
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
const int N=1e5+10;
int main()
{
int x;
cin>>x;
int f=x%2;

if(x==1) printf("Yang\n");
else printf("Shi\n");
}

B 小雨的三角形 水题一个。

按照题目给的牛客小白月赛16(部分题解A~H、J)_#include

处理好初始数列阵,对每一行求和,然后进行前缀和。那么查询的时候就可以O(1)搞了

/*¼ò»¯°æ*/
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
const int N=1e3+10;
const ll mod=1e9+7;
ll dp[N][N];
ll ans[N];
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<N;++i){
dp[i][1]=i;
dp[i][i]=i;
}
for(int i=3;i<N;++i){
for(int j=2;j<i;++j){
dp[i][j]=(dp[i-1][j]+dp[i-1][j-1])%mod;
}
}

for(int i=1;i<N;++i){
ll sum=0;
for(int j=1;j<=i;++j){
sum=(sum+dp[i][j])%mod;
}
//printf("sum:%lld\n",sum);
ans[i]=(ans[i-1]+sum)%mod;
}
while(m--){
int u,v;
scanf("%d%d",&v,&u);
printf("%lld\n",(ans[u]-ans[v-1]+mod)%mod);
}
}

C 小石的海岛之旅

n^2做法就可以过了。。

搞个vis数组标记1代表着这个岛是被淹没的了。然后一层for去判断有多少个连续的岛屿(vis连续的0)

/*¼ò»¯°æ*/
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
const int N=1e3+10;
const ll mod=1e9+7;
int a[N],q[N];
int vis[N];
int main(){
int n,m;
cin>>n>>m;
rep(i,1,n) cin>>a[i];
rep(i,1,m) cin>>q[i];
for(int j=1;j<=m;++j){
int d=q[j];
for(int i=1;i<=n;++i) if(a[i]<=d) vis[i]=1;
int ans=0;
int pre=-1;
for(int i=1;i<=n;++i){
if(pre==-1){
pre=vis[i];continue;
}
if(vis[i]==pre){
continue;
}
else{
if(pre==0) ans++;
pre=vis[i];
}
}
if(pre==0) ans++;
printf("%d\n",ans);
}

}

D-小阳买水果

维护前缀和的最大值至线段树里面,每次枚举前缀和,在当前位置到最后的区间里查找最大值,优先查找右儿子的最大值,大于当前前缀和(优先右儿子 保证了距离最远)

/*¼ò»¯°æ*/
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
const int N=2e6+10;
const ll mod=1e9+7;
int sum[N],s[N*4];
int n;
void up(int id,int l,int r,int pos){
if(l==r){
s[id]=sum[l];
return ;
}
int mid=l+r>>1;
if(pos<=mid) up(id<<1,l,mid,pos);
else up(id<<1|1,mid+1,r,pos);
s[id]=max(s[id<<1],s[id<<1|1]);
}
int qu(int id,int l,int r,int val){

if(l==r){
//printf("llll:%d\n",l);
return l;
}
int ans=0;
int mid=l+r>>1;
//printf("id:%d val:%d id<<1|1:%d\n",id,val,s[id<<1|1]);
if(s[id<<1|1]>val) return qu(id<<1|1,mid+1,r,val);
if(s[id<<1]>val)return qu(id<<1,l,mid,val);
return -1;
}
int main(){
cin>>n;
rep(i,1,n){
int x;
scanf("%d",&x);
sum[i]=sum[i-1]+x;
}

for(int i=1;i<=n;++i){
up(1,1,n,i);
}
int ans=0;
for(int i=0;i<=n;++i){
int id=qu(1,1,n,sum[i]);
if(id==-1) continue;

ans=max(ans,id-i);
}
printf("%d\n",ans);
}

E-小雨的矩阵

dfs水题,谁现在还不会dfs,去操场拿根草吊死。

每次dfs时有两个方向可以走,向下或向右。。到达终点return


/*¼ò»¯°æ*/
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
const int N=10;
const ll mod=1e9+7;
int a[N][N];
int n;
map<int,int>ma;
int ans;
void dfs(int l,int r,int num){
num+=a[l][r];
if(l>n||r>n) return ;
if(l==r&&l==n) {
if(ma[num]==0){
ma[num]=1;
ans++;
}
return ;
}
dfs(l+1,r,num);
dfs(l,r+1,num);
}
int main(){
cin>>n;
rep(i,1,n)
rep(j,1,n) cin>>a[i][j];
dfs(1,1,0);
printf("%d\n",ans);
}

F-小石的妹子

对于两个关键字肯定是不能排序贪心的,因为会有不确定因素。

所以我的做法是先将ai从大到小排序,对bi最大值建树,当前ans=查询比当前bi大的区间内最大值+1。然后将这个ans按照bi为下标插入到线段树里面去即可。

#include <bits/stdc++.h>

using namespace std;
const int N=1e5+10;
struct node{
int l,r,id;
}a[N];
int n,tot;
int ans[N],b[N],mx[N*4];
bool cmp(node a,node b){
if(a.l==b.l) return a.r>b.r;
return a.l>b.l;
}
int getid(int x){
return lower_bound(b+1,b+1+tot,x)-b;
}
int qu(int id,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr){
return mx[id];
}
int mid=l+r>>1;
int ans=0;
if(ql<=mid) ans=max(ans,qu(id<<1,l,mid,ql,qr));
if(qr>mid) ans=max(ans,qu(id<<1|1,mid+1,r,ql,qr));
return ans;
}
void up(int id,int l,int r,int pos,int val){
if(l==r){
mx[id]=val;
return ;
}
int mid=l+r>>1;
if(pos<=mid) up(id<<1,l,mid,pos,val);
else up(id<<1|1,mid+1,r,pos,val);
mx[id]=max(mx[id<<1],mx[id<<1|1]);
}
int main()
{
cin>>n;
for(int i=1;i<=n;++i){
scanf("%d%d",&a[i].l,&a[i].r);
a[i].id=i;
b[i]=a[i].r;
}
sort(a+1,a+1+n,cmp);
sort(b+1,b+1+n);
tot=unique(b+1,b+1+n)-b-1;
for(int i=1;i<=n;++i){
int mx=qu(1,1,tot,getid(a[i].r)+1,tot);
ans[a[i].id]=mx+1;
up(1,1,tot,getid(a[i].r),mx+1);
}
for(int i=1;i<=n;++i) printf("%d\n",ans[i]);
return 0;
}

G-小石的图形

给半圆的周长求其面积,初中题。。

牛客小白月赛16(部分题解A~H、J)_#include_02

这里的Π pai  用const double pi=acos(-1); 表示

/*¼ò»¯°æ*/
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
const double pi=acos(-1);
int main(){
double n;
cin>>n;
printf("%.3lf\n",n*n/(2*pi));
}

H-​​小阳的贝壳​​ 

另写了一个博客:线段树维护差分数组:​​博客传送门​

#include<bits/stdc++.h>
using namespace std;
#define ls id<<1
#define rs id<<1|1
const int N=1e5+10;
int gcd[N*4],mx[N*4],mi[N*4],T[N*4],n,m,a[N];
void up(int id,int l,int r,int pos,int val)
{
if(l==r)
{
mx[id]+=val;
mi[id]=gcd[id]=mx[id];
gcd[id]=abs(gcd[id]);///绝对值??
return ;
}
int mid=l+r>>1;
if(pos<=mid)up(ls,l,mid,pos,val);
else up(rs,mid+1,r,pos,val);
mx[id]=max(mx[ls],mx[rs]);
mi[id]=min(mi[ls],mi[rs]);
gcd[id]=__gcd(gcd[ls],gcd[rs]);
}
void up2(int id,int l,int r,int ql,int qr,int v)
{
if(ql<=l&&r<=qr){
T[id]+=v;
return;
}
int mid=l+r>>1;
if(ql<=mid) up2(ls,l,mid,ql,qr,v);
if(qr>mid) up2(rs,mid+1,r,ql,qr,v);
}
int qu2(int id,int l,int r,int pos)
{
if(l==r) return T[id];
int res=T[id];
int mid=l+r>>1;
if(pos<=mid) res+=qu2(ls,l,mid,pos);
else res+=qu2(rs,mid+1,r,pos);
return res;
}
int qu(int id,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr){
return max(abs(mx[id]),abs(mi[id]));
}
int mid=l+r>>1;
int res=0;
if(ql<=mid) res=max(res,qu(ls,l,mid,ql,qr));
if(qr>mid) res=max(res,qu(rs,mid+1,r,ql,qr));
return res;
}
int qugcd(int id,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr) return gcd[id];
int mid=l+r>>1;
if(qr<=mid) return qugcd(ls,l,mid,ql,qr);
else if(ql>mid) return qugcd(rs,mid+1,r,ql,qr);
else{
int t1=qugcd(ls,l,mid,ql,qr);
int t2=qugcd(rs,mid+1,r,ql,qr);
return __gcd(t1,t2);
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
up(1,1,n,i,a[i]-a[i-1]);
up2(1,1,n,i,i,a[i]);
}
int ans;
while(m--){
int ty,l,r;
scanf("%d%d%d",&ty,&l,&r);
if(ty==1){
int x;
scanf("%d",&x);
up(1,1,n,l,x);
if(r+1<=n) up(1,1,n,r+1,-x);
up2(1,1,n,l,r,x);
}
else if(ty==2){
if(l==r) printf("0\n");
else{
ans=qu(1,1,n,l+1,r);//因为是差分数组,所以l要加1
printf("%d\n",ans);
}
}
else{
int v=qu2(1,1,n,l);
if(l==r) printf("%d\n",v);
else{
int gc=qugcd(1,1,n,l+1,r);
printf("%d\n",__gcd(gc,v));//左端点的值gcd上差分数组内的gcd
}
}
}
}

I-​​石头剪刀布​


J-​​小雨坐地铁​

建m+1层图,跑最短路就可以了 博客 ​

/*简化版*/
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
const int N=1e3+10,M=520;
const int maxn=5e5+100;
int n,m,s,t,a[N],b[N];
vector<int>G[N*M];
int sub[N*M];
bool vis[N*M];
int dis[N*M];
struct node{
int pos,id;
int w;
bool operator <(const node &a)const {
return a.w<w;
}
};
void bfs()
{
priority_queue<node>que;
que.push({s,0,0});
dis[s]=0;
while(que.size()){
node u=que.top();que.pop();
if(vis[u.pos]) continue;
vis[u.pos]=1;
//printf("pos:%d u.id:%d dis:%d\n",u.pos,u.id,u.w);
for(int i=0;i<G[u.pos].size();++i){
int v=G[u.pos][i];
int w=0;
int id=u.id;
if(sub[v]!=id) w+=a[sub[v]];
else w+=b[sub[v]];
//printf("v:%d w:%d\n",v,w);
if(dis[v]>dis[u.pos]+w){
dis[v]=dis[u.pos]+w;
if(!vis[v]) que.push({v,sub[v],dis[v]});
}
}
}
if(dis[t]==0x3f3f3f3f)
printf("-1\n");
else printf("%d\n",dis[t]);
}
int main()
{
cin>>n>>m>>s>>t;
for(int i=1;i<=m;++i){
int c;
scanf("%d%d%d",&a[i],&b[i],&c);
int x,y;
scanf("%d",&y);
sub[(i-1)*N+y]=i;
G[y+500*N].push_back((i-1)*N+y);
G[(i-1)*N+y].push_back(y+500*N);
sub[(i-1)*N+y]=i;
--c;
while(c--){
scanf("%d",&x);
G[x+500*N].push_back((i-1)*N+x);
G[(i-1)*N+x].push_back(x+500*N);
sub[(i-1)*N+x]=i;

G[(i-1)*N+y].push_back((i-1)*N+x);
G[(i-1)*N+x].push_back((i-1)*N+y);
y=x;
}
}
mem(dis,0x3f3f3f3f);
if(s==t){
printf("0\n");
exit(0);
}
a[0]=b[0]=0;
s=500*N+s;
t=500*N+t;
bfs();
return 0;
}