牛客算法周周练15 解题报告

A-数列下标

题意:给你一个序列A,求出一个数列B.

其中Bi表示数列A中Ai右边第一个比Ai大的数的下标(从1开始计数),没有找到这一个下标 Bi 就为0

样例输入

6
3 2 6 1 1 2 

输出:

3 3 0 6 6 0 

题意解读:

从当前下标开始数

第一个比3大的数是6,B为3

第一个比2大的数是6,B为3

没有比6大的数,         B为0

第一个比1大的数为2,B为6

第一个比1大的数为2,B为6

没有比2大的数             B为0

因此B数列为{3 3 0 6 6 0}

hint:可以直接套用单调栈,需要求第一个比ai大的数,那么从后往前遍历,并运用单调递减栈,如果栈大小不为0的时候,栈顶就是所求的B,如果栈大小为0,就说明i到n并没有比Ai更大的数了,因此B为0

AC代码: 

#include<bits/stdc++.h>
using namespace std;
const int N = 1e4+5;
typedef long long LL;
stack<int>s;//栈存放的是下标
int a[N],b[N];
int main(){
    int n;cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    for(int i=n;i>=1;i--){
        while(s.size()&&a[s.top()]<=a[i])s.pop();
        if(s.size())b[i]=s.top();
        else b[i]=0;
        s.push(i);
    }
    for(int i=1;i<=n;i++){
        if(i!=1)cout<<" ";
        cout<<b[i];
    }
    system("pause");
    return 0;
}

B-可持久化动态图上树状数组维护01背包 

题意:

 样例输入:

2

2 3

 输出:

5

hint:(贪心)

对于正数,那么就是i*ai中的i越小越好,就是从前往后取代价最小,因为如果不这么做,比如x y z,原先是x+y+z,如果不这么做,那么就是y*2+z*2+x或者是z*3+y*2+x,代价会多出y+z或者是y+z*2。

对于负数,那么就是i*ai中的i越大越好,就是从后往前取了,此时i就是对应下标,如果不这么做,同理就会少减,使得代码变大。

还有就是i*a[i]会爆int,ans取long long就好。

AC代码: 

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+5;
typedef long long LL;
int a[N];
int main(){
    int n;cin>>n;
    LL ans=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        if(a[i]>0)ans=ans+1LL*a[i];
        else ans=ans+1LL*a[i]*i;
    }
    cout<<ans;
    system("pause");
    return 0;
}

D-树上求和

题意:一棵根为1的N个节点的树,进行Q次操作,操作如下,针对每次询问输出结果。

输入

5 5
0 0 0 0 0
1 2
1 3
3 4
3 5
1 1 3
1 3 7
1 4 5
1 5 6
2 1

输出:

599

hint:直接用dfs暴搜,模拟一下就好

#include<bits/stdc++.h>
#define PB push_back
#define PII pair<int,int>
#define PLL pair<long long,long long>
#define FI first
#define SE second
#define mem(a) memset(a,0,sizeof(a))
#define sc1(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int INF = 0x3f3f3f3f;
const double pi=acos(-1),eps=1e-8;
const LL maxn = 1<<17;
const int mod = 23333;
const int N = 1e5+5;
int a[N],f[N];
vector<int>v[N];
void add(int x,int y){
	v[x].PB(y);
	v[y].PB(x);
}

//dfs建树
void dfs(int s,int fa){
	for(auto i:v[s]){
		if(i==fa)continue;
		f[i]=s;
		dfs(i,s);
	}
}

//操作1 子树结点加Num 
void dfs1(int s,int fa,int num){
	for(auto i:v[s]){
		if(i==fa)continue;
		dfs1(i,s,num);
		a[i]=(a[i]+num)%mod;
	}
}

//操作二 查询子树结点权值平方和
int dfs2(int s,int fa){
	int ans=0;
	for(auto i:v[s]){
		if(i==fa)continue;
		int num=dfs2(i,s);
		ans=(ans+num)%mod;
	}
	return (ans+1LL*a[s]*a[s])%mod;
}
int main(){
	int n,q;
	sc2(n,q);
	for(int i=1;i<=n;i++){
		sc1(a[i]);
	}
	for(int i=1;i<n;i++){
		int x,y;
		sc2(x,y);
		add(x,y);
	}
	f[1]=-1;
	dfs(1,-1);
	while(q--){
		int op,x,y;
		sc1(op);
		if(op==1){
			sc2(x,y);
			dfs1(x,f[x],y);
			a[x]=(a[x]+y)%mod;
		}else if(op==2){
			sc1(x);
			printf("%d\n",dfs2(x,f[x]));
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43911947/article/details/107417584
今日推荐