牛客小白月赛9 A、B、C、D、E、H

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37960603/article/details/84628647

传送门

A
被砸到的概率 = 1 - 不被砸到的概率
而不被砸到的概率很容易计算。
代码:

#include<cstdio>
using namespace std;
 
typedef long long ll;
const ll mod=1e9+7;
const int maxn=100000+100;
 
ll mypow(ll a,ll b){
    ll sum=1;
    while(b){
        if(b&1) sum=sum*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return sum;
}
 
ll fz[maxn],fm[maxn];
 
int main(){
    int n;
    scanf("%d",&n);
    ll ans=1;
    for(int i=1;i<=n;i++){
        scanf("%lld%lld",&fz[i],&fm[i]);
        ll tmp=mypow(fm[i],mod-2);
        ans=(ans*(fm[i]-fz[i])%mod*tmp)%mod;
    }
    printf("%lld\n",(1-ans+mod)%mod);
}

B
代码:

#include<cstdio>
using namespace std;

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        long long n;
        scanf("%lld",&n);
        if(n<=2) printf("1\n");
        else printf("0\n");
    }
}

C
线段树很容易做出来。
代码:

#include<cstdio>
using namespace std;

typedef long long ll;
const int maxn=100000+100;

struct Tree{
	ll val;
	int Xor;
	int num;
	int bit[20];
}tree[maxn<<2];

int val[maxn];

void build(int rt,int l,int r){
	if(l==r){
	    for(int i=0;i<20;i++) if((val[l]>>i)&1) tree[rt].bit[i]=1;
	    tree[rt].val=val[l];
	    tree[rt].num=1;
	    tree[rt].Xor=0;
		return ;
	}
	int mid=(l+r)>>1;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid+1,r);
	for(int i=0;i<20;i++) tree[rt].bit[i]=(tree[rt<<1].bit[i]+tree[rt<<1|1].bit[i]);
	tree[rt].num=(r-l+1);
	tree[rt].Xor=0;
	tree[rt].val=(tree[rt<<1].val+tree[rt<<1|1].val);
}

void updateDown(int rt,int l,int r,int mid){
	int Xor=tree[rt].Xor;
	tree[rt<<1].Xor^=Xor;
	tree[rt<<1|1].Xor^=Xor;
	for(int i=0;i<20;i++){
		if((Xor>>i)&1){
			tree[rt<<1].bit[i]=tree[rt<<1].num-tree[rt<<1].bit[i];
			tree[rt<<1|1].bit[i]=tree[rt<<1|1].num-tree[rt<<1|1].bit[i];
		}
	}
	if(l==mid) tree[rt<<1].val^=Xor;
	else{
		tree[rt<<1].val=0;
		for(int i=0;i<20;i++)  tree[rt<<1].val+=((1LL*tree[rt<<1].bit[i])<<i); 
	}
	if(mid+1==r) tree[rt<<1|1].val^=Xor;
	else{
		tree[rt<<1|1].val=0;
		for(int i=0;i<20;i++)  tree[rt<<1|1].val+=((1LL*tree[rt<<1|1].bit[i])<<i);
	}
	tree[rt].Xor=0;
}

void update(int rt,int l,int r,int L,int R,int Xor){
	if(L<=l && R>=r){
		tree[rt].Xor^=Xor;
		for(int i=0;i<20;i++){
			if((Xor>>i)&1){
				tree[rt].bit[i]=tree[rt].num-tree[rt].bit[i];
			}
		}
		tree[rt].val=0;
		for(int i=0;i<20;i++) tree[rt].val+=((1LL*tree[rt].bit[i])<<i);
		return ;
	}
	int mid=(l+r)>>1;
	if(tree[rt].Xor) updateDown(rt,l,r,mid);
	if(L<=mid) update(rt<<1,l,mid,L,R,Xor);
	if(R>mid) update(rt<<1|1,mid+1,r,L,R,Xor);
	for(int i=0;i<20;i++) tree[rt].bit[i]=(tree[rt<<1].bit[i]+tree[rt<<1|1].bit[i]);
	tree[rt].val=(tree[rt<<1].val+tree[rt<<1|1].val);
}

ll query(int rt,int l,int r,int L,int R){
	if(L>r || R<l) return 0;
	if(L<=l && R>=r) return tree[rt].val;
	int mid=(l+r)>>1;
	if(tree[rt].Xor) updateDown(rt,l,r,mid);
	return query(rt<<1,l,mid,L,R)+query(rt<<1|1,mid+1,r,L,R);
}

int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&val[i]);
	build(1,1,n);
	for(int i=1;i<=m;i++){
		int type,l,r,k;
		scanf("%d",&type);
		if(type==1){
			scanf("%d%d",&l,&r);
			printf("%lld\n",query(1,1,n,l,r));
		}
		else{
			scanf("%d%d%d",&l,&r,&k);
			if(k) update(1,1,n,l,r,k);
		}
	}
}

D
由于都是在某一棵子树上操作,所以并不一定需要使用树链剖分,只要根据树链剖分的思想进行重编号,记录每棵子树的编号范围即可,再用线段树维护。
代码:

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

typedef long long ll;
const int maxn=100000+100;
const int mod=23333;

struct Tree{
	ll add;
	ll two;
	ll mul;
}tree[maxn<<2];
int id[maxn],maxid[maxn],rev[maxn],id_cnt;
bool vis[maxn];

struct Edge{
	int to,next;
}edge[maxn<<1];
int head[maxn],tot;

int val[maxn];

void init(){
	memset(head,-1,sizeof(head));
	memset(vis,false,sizeof(vis));
	tot=id_cnt=0;
}

void addEdge(int u,int v){
	edge[tot].to=v;
	edge[tot].next=head[u];
	head[u]=tot++;
	edge[tot].to=u;
	edge[tot].next=head[v];
	head[v]=tot++;
}

void dfs(int u){
	vis[u]=true;
	id[u]=maxid[u]=(++id_cnt);
	rev[id_cnt]=u;
	for(int i=head[u];i!=-1;i=edge[i].next){
		Edge e=edge[i];
		if(!vis[e.to]){
			dfs(e.to);
			maxid[u]=max(maxid[u],maxid[e.to]);
		}
	}
}

void build(int rt,int l,int r){
	if(l==r){
		int v=val[rev[l]];
		tree[rt].mul=v;
		tree[rt].two=v*v;
		tree[rt].add=0;
		return ;
	}
	int mid=(l+r)>>1;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid+1,r);
	tree[rt].mul=(tree[rt<<1].mul+tree[rt<<1|1].mul);
	tree[rt].two=(tree[rt<<1].two+tree[rt<<1|1].two);
	tree[rt].mul%=mod;
	tree[rt].two%=mod;
	tree[rt].add=0;
}

void updateDown(int rt,int l,int r,int mid){
	ll Add=tree[rt].add;
	tree[rt<<1].add+=Add;
	tree[rt<<1|1].add+=Add;
	tree[rt<<1].two+=((mid-l+1)*Add*Add+tree[rt<<1].mul*2*Add);
	tree[rt<<1|1].two+=((r-mid)*Add*Add+tree[rt<<1|1].mul*2*Add);
	tree[rt<<1].mul+=((mid-l+1)*Add);
	tree[rt<<1|1].mul+=((r-mid)*Add);
	tree[rt<<1].add%=mod;
	tree[rt<<1|1].add%=mod;
	tree[rt<<1].mul%=mod;
	tree[rt<<1|1].mul%=mod;
	tree[rt<<1].two%=mod;
	tree[rt<<1|1].two%=mod;
	tree[rt].add=0;
}

void update(int rt,int l,int r,int L,int R,int v){
	if(L<=l && R>=r){
		tree[rt].add+=v;
		tree[rt].two+=(1LL*(r-l+1)*v*v+tree[rt].mul*2*v);
		tree[rt].mul+=(1LL*(r-l+1)*v);
		tree[rt].add%=mod;
		tree[rt].mul%=mod;
		tree[rt].two%=mod;
		return ;
	}
	int mid=(l+r)>>1;
	if(tree[rt].add) updateDown(rt,l,r,mid);
	if(L<=mid) update(rt<<1,l,mid,L,R,v);
	if(R>mid) update(rt<<1|1,mid+1,r,L,R,v);
	tree[rt].mul=(tree[rt<<1].mul+tree[rt<<1|1].mul);
	tree[rt].two=(tree[rt<<1].two+tree[rt<<1|1].two);
	tree[rt].mul%=mod;
	tree[rt].two%=mod;
}

int query(int rt,int l,int r,int L,int R){
	if(L>r || R<l) return 0;
	if(L<=l && R>=r) return tree[rt].two;
	int mid=(l+r)>>1;
	if(tree[rt].add) updateDown(rt,l,r,mid);
	return (query(rt<<1,l,mid,L,R)+query(rt<<1|1,mid+1,r,L,R))%mod;
}

int main(){
	init();
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&val[i]),val[i]%=mod;
	for(int i=1;i<n;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		addEdge(u,v);
	}
	dfs(1);
	build(1,1,n);
	for(int i=1;i<=m;i++){
		int type,x,y;
		scanf("%d",&type);
		if(type==1){
			scanf("%d%d",&x,&y);
			//printf("%d %d\n",id[x],maxid[x]);
			y%=mod;
			update(1,1,n,id[x],maxid[x],y);
		}
		else{
			scanf("%d",&x);
			printf("%d\n",query(1,1,n,id[x],maxid[x])); 
		}
	}
}

E
只需要记录 <= x 的 a[i] 信息,所以先排序,位置信息由树状数组来维护。
代码:

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

const int maxn=100000+100;

int n,m;
struct Node{
	int l,r,id,val;
	bool operator <(const Node a)const{
	    return a.val>val;
	}
}node[maxn];
struct Val{
	int id,val;
	bool operator <(const Val a)const{
	    return a.val>val;
	}
}val[maxn];
int ans[maxn];

int tree[maxn];

int getSum(int x){
	int sum=0;
	while(x>0){
		sum+=tree[x];
		x-=(x&(-x));
	}
	return sum;
}

void update(int x){
	while(x<=n){
		tree[x]++;
	//	printf("%d %d\n",tree[x],x);
		x+=(x&(-x));
	}
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&val[i].val),val[i].id=i;
	for(int i=1;i<=m;i++) scanf("%d%d%d",&node[i].l,&node[i].r,&node[i].val),node[i].id=i;
	sort(val+1,val+n+1);
	sort(node+1,node+m+1);
	for(int i=1,j=1;i<=m;i++){
		for(;j<=n && node[i].val>=val[j].val;j++){
			update(val[j].id);
			//printf("%d %d %d\n",node[i].val,val[j].val,val[j].id);
		}
		//printf("%d\n",getSum(node[i].r));
		ans[node[i].id]=getSum(node[i].r)-((node[i].l==1)?0:getSum(node[i].l-1));
	}
	for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
} 

H
代码:

#include<cstdio>
using namespace std;
 
int main(){
    long long n;
    scanf("%lld",&n);
    if(n!=1) printf("%lld\n",n+(n-1));
    else printf("2\n");
}

猜你喜欢

转载自blog.csdn.net/qq_37960603/article/details/84628647