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

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

地址链接: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 小雨的三角形 水题一个。

按照题目给的

处理好初始数列阵,对每一行求和,然后进行前缀和。那么查询的时候就可以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-小石的图形

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

这里的Π 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层图,跑最短路就可以了 博客:https://blog.csdn.net/qq_41286356/article/details/95865445

/*简化版*/
#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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长沙大学ccsu_deer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值