好久没写树状数组了,回忆一下
一道板子题,统计v和^的个数,每个点可能是v的尖,也可能 是^的尖。
所以我们可以统计一下一个点左边和右边分别有多少大于小于它的,
然后每个点的构成方案数为左边小(大)*右边小(大);
#include<bits/stdc++.h>
#define int long long
#define lowbit(x) ((x)&(-(x)))
const int N=1e6;
int a[N],tr[N],n;
int low[N],gre[N];
using namespace std;
void add(int x){
for(int i=x;i<=n;i+=lowbit(i))tr[i]++;
}
int ask(int x){
int ans(0);
for(int i=x;i;i-=lowbit(i))ans+=tr[i];
return ans;
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
gre[i]=ask(n)-ask(a[i]);
low[i]=ask(a[i]-1);
add(a[i]);
}
for(int i=1;i<=n;i++)tr[i]=0;
int cv(0),cx(0);
for(int i=n;i>=1;i--){
cv+=gre[i]*(ask(n)-ask(a[i]));
cx+=low[i]*ask(a[i]-1);
add(a[i]);
}
cout<<cv<<' '<<cx<<endl;
return 0;
}
也是一道板子题,之前写的时候用的是yxc的差分数组的方法,然后今天写了一下,但是没有用差分,直接原数加上修改值也是可以的
#include<bits/stdc++.h>
#define int long long
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int N=1e6;
int n,m;
int a[N],tr[N];
void add(int x,int d){
for(int i=x;i<=n;i+=lowbit(i))tr[i]+=d;
}
int ask(int x){
int ans=a[x];
for(int i=x;i;i-=lowbit(i))ans+=tr[i];
return ans;
}
signed main(){
cin>>n>>m;
for(int i=1;i<=n;++i)cin>>a[i];
while(m--){
char op;
cin>>op;
if(op=='C'){
int l,r,d;
cin>>l>>r>>d;
add(l,d);
add(r+1,-d);
}
else{
int x;
cin>>x;
cout<<ask(x)<<endl;
}
}
return 0;
}