精选竞赛题单(数据结构)

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

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Smile灬凉城666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值