1.树状数组
P3374 【模板】树状数组 1 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<bits/stdc++.h>
#define int long long
#define PII pair<int,int>
#define PCC pair<cahr,char>
#define PSS pair<string,string>
#define endl "\n"
#define INF 0x3f3f3f3f
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
//vector<int> vec;
set<int> sei;
multiset<string> ses;
map<int, int> mp;
const int N = 1e6 + 7;
int n, m;
int s[N];
int lowbit(int i) {
return i & (-i);
}
void add(int b, int a) {
for (int i = b; i <= n; i += lowbit(i)) {
s[i] += a;
}
}
int sum(int e) {
int ans = 0;
for (int i = e; i > 0; i -= lowbit(i)) {
ans += s[i];
}
return ans;
}
int sum(int a, int b) {
return sum(b) - sum(a - 1);
}
void solution() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
int a;
cin >> a;
add(i, a);
}
while (m--) {
int k;
int o, p;
//cout<<1;
cin >> k;
cin >> o >> p;
// cout<<k<<endl;
if (k == 1) {
add(o, p);
} else {
cout << sum(o, p) << endl;
}
}
}
signed main() {
solution();
system("pause");
return 0;
}
P3368 【模板】树状数组 2 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define lowbit(x) x&-x
map<int, int> mp;
const int N = 1e6 + 7;
int sum1[N], sum2[N];
int a[N];
int n, m;
void add(int i, int k) {
for (int j = i; j <= n; j += lowbit(j)) {
sum1[j] += k;
sum2[j] += i * k;
}
}
int sum(int n) {
int ans = 0;
for (int i = n; i > 0; i -= lowbit(i)) {
ans += sum1[i];
}
return ans;
}
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
add(i, a[i] - a[i - 1]);
}
while (m--) {
int k;
cin >> k;
if (k == 1) {
int x, y, k;
cin >> x >> y >> k;
add(x, k);
add(y + 1, -k);
} else {
int c;
cin >> c;
cout << sum(c) << endl;
}
}
return 0;
}
P1908 逆序对 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define lowbit(x) x&-x
const int N = 1e6 + 7;
int a[N], b[N], c[N];
int cnt = 1;
int tr[N];
int n;
map<int, int> mp;
void add(int x, int k) {
for (int i = x; i <= n; i += lowbit(i)) {
tr[i] += k;
}
}
int query(int x) {
int res = 0;
for (int i = x; i > 0; i -= lowbit(i)) {
res += tr[i];
}
return res;
}
//离散化
void find(int x) {
if (!mp.count(x)) {
mp[x] = cnt++;
}
}
signed main() {
ios::sync_with_stdio(false);
scanf("%lld", &n);
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
c[i] = a[i];
}
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i++) {
find(a[i]);
}
// for (auto [x, y] : mp) {
// cout << x << " " << y << endl;
// }
int sum = 0;
for (int i = n; i > 0; i--) {
sum += query(mp[c[i]]-1);
add(mp[c[i]], 1);
}
cout << sum;
return 0;
}
P1774 最接近神的人 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
//不开long long 见祖宗
#include<cstdio>
#include<iostream>
#include<cmath>
#include<map>
#include<algorithm>
using namespace std;
#define int long long
#define lowbit(x) x&-x
const int N=1e6+7;
int tre[N];
int a[N] , b[N];
int n;
int cnt = 1;
map<int,int> mp;
inline void add(int x,int k)
{
for(int i = x ; i <= n ; i += lowbit(i))
{
tre[i] += k;
}
}
inline int query(int x)
{
int res = 0;
for(int i = x ; i > 0 ; i -= lowbit(i))
{
res += tre[i];
}
return res ;
}
signed main()
{
cin >> n ;
int sum = 0 ;
for(int i = 1 ; i <= n ; i ++)
{
cin >> a[i] ;
b[i] = a[i];
}
sort(b + 1, b +n +1);
for(int i = 1; i <= n; i ++)
{
if(!mp.count(mp[b[i]]))
{
mp[b[i]] = cnt ++;
}
}
for(int i = n ; i > 0 ; i --)
{
add(mp[a[i]] , 1);
sum += query(mp[a[i]] - 1);
}
cout << sum << endl;
}
楼兰图腾 (nowcoder.com)
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define lowbit(x) x&-x
const int N = 1001000;
int Greater[N];
int Lower[N];
int a[N];
int tru[N];
int n;
void add(int x, int k) {
for (int i = x; i <= n; i += lowbit(i)) {
tru[i] += k;
}
return ;
}
LL query(int x) {
int sum = 0;
for (int i = x; i > 0; i -= lowbit(i)) {
sum += tru[i];
}
return sum;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i <= n; i++) {
Greater[i] = query(n) - query(a[i]);
Lower[i] = query(a[i] - 1);
add(a[i], 1);
}
LL res1 = 0, res2 = 0;
memset(tru, 0, sizeof tru);
for (int i = n; i > 0; i--) {
res1 += Greater[i] * (LL) (query(n) - query(a[i]));
res2 += Lower[i] * (LL)query(a[i] - 1);
add(a[i], 1);
}
cout << res1 << " " << res2 << endl;
return 0;
}
P4939 Agent2 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
差分数组 + 树状数组 维护 区间修改单点查询
#include<cstdio>
#include<iostream>
#include<cmath>
#include<map>
#include<algorithm>
using namespace std;
#define int long long
#define lowbit(x) x&-x
const int N=1e7+7;
int tre[N];
int n , m ;
inline void add(int x,int k)
{
for(int i = x ; i <= n ; i += lowbit(i))
{
tre[i] += k;
}
}
inline int query(int x)
{
int res = 0;
for(int i = x ; i > 0 ; i -= lowbit(i))
{
res += tre[i];
}
return res ;
}
signed main()
{
cin >> n >> m ;
while(m -- )
{
int ch;
cin >> ch ;
if(ch == 0)
{
int l ,r ;
cin >> l >> r ;
add(l, 1) , add(r + 1 ,-1);
}else
{
int oq;
cin >> oq;
cout<< query(oq) << endl;
}
}
return 0;
}
P2357 守墓人 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
第一种解法 :树状数组
差分数组 + 树状数组 维护 区间修改 区间查询
#include<bits/stdc++.h>
#define int long long
#define PII pair<int,int>
#define PCC pair<cahr,char>
#define PSS pair<string,string>
#define endl "\n"
#define INF 0x3f3f3f3f
#define RI register int
#define IL inline
#define lowbit(x) x&-x
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 1e6 + 7;
int a[N], sum1[N], sum2[N];
int n, m;
IL void add(int i, int k) {
for (int j = i; j <= n; j += lowbit(j)) {
sum1[j] += k;
sum2[j] += k * i;
}
}
IL int query(int pos) {
int ans = 0;
for (int j = pos; j > 0; j -= lowbit(j)) {
ans += (pos + 1) * sum1[j] - sum2[j];
}
return ans;
}
void solution() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
add(i, a[i] - a[i - 1]);
}
int maino = 0;
while (m--) {
int op;
cin >> op;
int l, r, k;
switch (op) {
case 1:
cin >> l >> r >> k;
add(l, k);
add(r + 1, -k);
break;
case 2:
cin >> k;
maino += k;
break;
case 3:
cin >> k;
maino -= k;
break;
case 4:
cin >> l >> r;
cout << query(r) - query(l - 1) + (l == 1)*maino << endl;
break;
case 5:
cout << query(1) + maino << endl;
break;
}
}
}
signed main() {
solution();
system("pause");
return 0;
}
第二种解法:线段树
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define SIOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N = 1e6 + 7;
map<int, int> mp;
int w[N];
struct node {
int l, r;
int sum, add;
} tr[4 * N];
int n, m;
//建树
void pushup(node& root, node& li, node& ri) {
root.sum = li.sum + ri.sum;
}
void pushup(int u) {
pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
void build(int u, int l, int r) {
tr[u].l = l, tr[u].r = r;
if (l == r) {
tr[u].sum = w[l];
return ;
}
int mid = (r + l) >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}
//区间修改
void pushdown(node& root, node& li, node& ri) {
li.add += root.add;
li.sum += (li.r - li.l + 1) * root.add;
ri.add += root.add;
ri.sum += (ri.r - ri.l + 1) * root.add;
root.add = 0;
}
void pushdown(int u) {
pushdown(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
void modify(int u, int l, int r, int k) {
if (tr[u].l >= l && tr[u].r <= r) {
tr[u].sum += (tr[u].r - tr[u].l + 1) * k;
tr[u].add += k;
} else {
pushdown(u);
int mid = (tr[u].l + tr[u].r) >> 1;
if (mid >= l)modify(u << 1, l, r, k);
if (mid < r)modify(u << 1 | 1, l, r, k);
pushup(u);
}
}
//区间查询
int query(int u, int l, int r) {
if (tr[u].l >= l && tr[u].r <= r) {
return tr[u].sum;
} else {
pushdown(u);
int mid = (tr[u].l + tr[u].r) >> 1;
int res = 0;
if (mid >= l)res += query(u << 1, l, r);
if (mid < r)res += query(u << 1 | 1, l, r);
return res;
}
}
signed main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> w[i];
build(1, 1, n);
int maino = 0;
while (m--) {
int op;
cin >> op;
int l, r, k;
switch (op) {
case 1:
cin >> l >> r >> k;
modify(1, l, r, k);
break;
case 2:
cin >> k;
maino += k;
break;
case 3:
cin >> k;
maino -= k;
break;
case 4:
cin >> l >> r;
cout << query(1, l, r) + (l == 1)*maino << endl;
break;
case 5:
cout << query(1, 1, 1) + maino << endl;
break;
}
}
return 0;
}
第三种解法:分块
#include<cstdio>
#include<cmath>
using namespace std;
#define LL long long
const int N=2e5+7;
LL a[N];
int q[N];
LL res[N];
LL sum[N];
int len,n,m;
inline int get(int i) {
return (i-1)/len+1;
}
inline void change(int l,int r,int k) {
if(get(l)==get(r)) {
for(int i=l; i<=r; i++) {
a[i]+=k;
res[get(i)]+=k;
}
} else {
int i=l,j=r;
while(get(l)==get(i)) a[i]+=k,res[get(i)]+=k,i++;
while(get(r)==get(j)) a[j]+=k,res[get(j)]+=k,j--;
for(int o=get(i); o<=get(j); o++) {
res[o]+=len*k;
sum[o]+=k;
}
}
}
inline LL query(int l,int r) {
LL ans=0;
if(get(l)==get(r)) {
for(int i=l; i<=r; i++) {
ans+=a[i]+sum[get(i)];
}
} else {
int i=l,j=r;
while(get(l)==get(i)) ans+=a[i]+sum[get(i)],i++;
while(get(r)==get(j)) ans+=a[j]+sum[get(j)],j--;
for(int o=get(i); o<=get(j); o++) {
ans+=res[o];
}
}
return ans;
}
int main() {
scanf("%d%d",&n,&m);
len=sqrt(n);
for(int i=1; i<=n; i++) {
scanf("%lld",&a[i]);
q[i]=get(i);
res[q[i]]+=a[i];
}
while (m--) {
int opt, q, l, r;
scanf("%d", &opt);
if (opt <= 3) {
if (opt == 1) {
scanf("%d%d%d", &l, &r, &q);
change(l, r, q);
} else {
scanf("%d", &q);
change(1, 1, opt == 2 ? q : -q);
}
} else {
if (opt == 4) scanf("%d%d", &l, &r), printf("%lld\n", query(l, r));
else printf("%lld\n", a[1] + sum[1]);
}
}
}
P1438 无聊的数列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这题用到了二阶差分 + 树状数组 (不推荐新手)
#include<bits/stdc++.h>
#define N 100009
using namespace std;
typedef long long ll;
ll n,m,a[N],d[N],bit1[N],bit2[N];
ll LSB(ll x){
return x&(-x);
}
void add(ll x,ll delta){
ll id=x;
while(x<=n){
bit1[x]+=delta;
bit2[x]+=delta*id;
x+=LSB(x);
}
}
ll query(ll x){
ll id=x,sum=0;
while(x){
sum+=(id+1)*bit1[x]-bit2[x];
x-=LSB(x);
}
return sum;
}
void input(){
scanf("%lld %lld",&n,&m);
for(ll i=1;i<=n;i++){
scanf("%lld",&a[i]);
d[i]=a[i]-a[i-1];
add(i,d[i]-d[i-1]);
}
}
void solve(){
for(ll i=1;i<=m;i++){
ll op;
scanf("%lld",&op);
if(op==1){
ll l,r,K,D;
scanf("%lld %lld %lld %lld",&l,&r,&K,&D);
add(l,K); add(l+1,D-K); add(r+1,-(r-l+1)*D-K); add(r+2,K+(r-l)*D);
}else{
ll p;
scanf("%lld",&p);
printf("%lld\n",query(p));
}
}
}
int main(){
input();
solve();
return 0;
}
2.ST表
P3865 【模板】ST 表 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<iostream>
#include<cstring>
#include<algorithm>
#define int long long
const int N = 1e4, M = 1e3;
using namespace std;
int n, m;
int a[N * N], Log[N];
int f[N][M];
void GetLog() {
int i;
Log[1] = 0;
for (i = 2; i <= n + 1; ++i)
Log[i] = Log[i / 2] + 1;
}
void RMQ() {
for (int i = 1; i <= n; i++)
f[i][0] = a[i];
for (int j = 1; (1 << j) <= n; j++)
for (int i = 1; i + (1 << (j - 1)) <= n; i++)
f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}
signed main() {
int l, r, k;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
GetLog();
RMQ();
int ans;
for (int i = 1; i <= m; i++) {
cin >> l >> r;
k = Log[r - l + 1];
ans = min(f[l][k], f[r - (1 << k) + 1][k]);
printf("%d\n", ans);
}
return 0;
}
P2880 [USACO07JAN] Balanced Lineup G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
const int N=1e6+7;
int maxx[N][21],minn[N][21];
int n,m;
signed main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>maxx[i][0];
minn[i][0]=maxx[i][0];
}
for(int j=1;j<=21;j++)
{
for(int i=1;i+(1<<(j-1))<=n;i++)
{
minn[i][j]=min(minn[i][j-1],minn[i+(1<<(j-1))][j-1]);
maxx[i][j]=max(maxx[i][j-1],maxx[i+(1<<(j-1))][j-1]);
}
}
while(m--)
{
int l,r;
cin>>l>>r;
int k=log2(r-l+1);
int x=max(maxx[l][k],maxx[r-(1<<k)+1][k]);
int y=min(minn[l][k],minn[r-(1<<k)+1][k]);
cout<<x-y<<endl;
}
return 0;
}