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;
}