树状数组,这工具人真好用,补下模板题,一家人就要整整齐齐。
AcWing 241. 楼兰图腾
题目链接
四个月前写了一次,现在又写了一次,两次虽处理方式不同,异曲同工.
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
const int N = 200010;
int tr[N];
int a[N],rt[N],lf[N];
int n;
int lowbit(int x){
return x&(-x);
}
ll getSum(int x){
ll res = 0;
while(x){
res += tr[x];
x -= lowbit(x);
}
return res;
}
void update(int x,int val){
for(;x<=n;x+=lowbit(x)){
tr[x] += val;
}
}
signed main()
{
std::ios::sync_with_stdio(false);std::cin.tie(nullptr);
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i];
for(int i=n;i>=1;i--){
rt[i] = getSum(n) - getSum(a[i]);
update(a[i],1);
}
memset(tr,0,sizeof tr);
for(int i=1;i<=n;i++){
lf[i] = getSum(n) - getSum(a[i]);
update(a[i],1);
}
ll ans1 = 0,ans2 = 0;
for(int i=1;i<=n;i++){
ans1 += rt[i]*lf[i];
ans2 += (n-i-rt[i])*(i-1-lf[i]);
}
cout << ans1 << " " << ans2 << endl;
return 0;
}
AcWing 242. 一个简单的整数问题
题目链接
思路:利用差分将题目转化为单点修改和区间查询,nice。
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
const int N = 100100;
int tr[N],a[N];
int n;
int lowbit(int x){
return x&(-x);
}
int getSum(int x){
int res = 0;
while(x){
res += tr[x];
x -= lowbit(x);
}
return res;
}
void update(int x,int val){
while(x<=n){
tr[x] += val;
x += lowbit(x);
}
}
signed main()
{
std::ios::sync_with_stdio(false);std::cin.tie(nullptr);
int m;
cin >> n >> m;
for(int i=1;i<=n;i++) cin >> a[i];
char s[3];
int l,r,d,x;
while(m--){
cin >> s;
if(*s=='C'){
cin >> l >> r >> d;
update(l,d);
update(r+1,-d);
}else{
cin >> x;
cout << (a[x] + getSum(x)) << endl;;
}
}
return 0;
}
AcWing 243. 一个简单的整数问题2
题目链接
oh谢,这题我好像拿分块写的,线段树和树状数组也能写(太麻烦),没必要。
/* 分块 */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100010;
ll sum[1010];
int add[1010],a[N];
int pos[N],L[1010],R[1010];
int n,m;
ll query(int l,int r){
ll ans = 0;
int p = pos[l],q = pos[r];
if(p==q){
for(int i=l;i<=r;i++) ans += a[i];
ans += (r - l + 1) * add[p];
}else{
for(int i=p+1;i<=q-1;i++){
ans += sum[i] + (R[i]-L[i]+1)*add[i];
}
for(int i=l;i<=R[p];i++){
ans += a[i];
}
ans += (R[p]-l+1)*add[p];
for(int i=L[q];i<=r;i++){
ans += a[i];
}
ans += (r-L[q]+1)*add[q];
}
return ans;
}
void modify(int l,int r,int val){
int p = pos[l],q = pos[r];
if(p==q){
for(int i=l;i<=r;i++){
a[i] += val;
}
sum[p] += (r - l + 1) * val;
}else{
for(int i=p+1;i<=q-1;i++) add[i] += val;
for(int i=l;i<=R[p];i++){
a[i] += val;
sum[p] += val;
}
for(int i=L[q];i<=r;i++){
a[i] += val;
sum[q] += val;
}
}
return;
}
int main()
{
std::ios::sync_with_stdio(false);std::cin.tie(nullptr);
cin >> n >> m;
for(int i=1;i<=n;i++) cin >> a[i];
//预处理
int t = sqrt(n);
for(int i=1;i<=t;i++){
L[i] = (i-1)*t + 1;
R[i] = i*t;
}
if(t*t!=n){
t++;
L[t] = R[t-1] + 1;
R[t] = n;
}
for(int i=1;i<=t;i++){
for(int j=L[i];j<=R[i];j++){
pos[j] = i;
sum[i] += a[j];
}
}
char op[3];
int l,r,d;
while(m--){
cin >> op;
if(*op=='C'){
cin >> l >> r >> d;
modify(l,r,d);
}else{
cin >> l >> r;
cout << query(l,r) << endl;
}
}
return 0;
}
AcWing 244. 谜一样的牛
题目链接
…倍增\二分+树状数组,好吧我不会,会了再回来。