2023年中国高校计算机大赛-团队程序设计天梯赛(GPLT)上海理工大学校内选拔赛 H 摘苹果

题目链接

算是比较入门的线段树题了

考虑线段树上维护三个值,sum维护总和,used维护当前结点是否还能进行操作,cnt100维护当前结点里面树上苹果数量少于100的树的数量。

我们可以发现每颗树上最多有1e9颗苹果,我们每次减去他三分之一,估算一下每颗树进行50次(k)以内的操作可以做到苹果数量小于10,每颗树遍历一次是log(n)级别的复杂度,因此总的操作复杂度为n * k * log(n)约为 1e8的时间复杂度。我们每次操作区间的时候,对于能进行操作的区间一直递归到最深,然后每当一颗树上的苹果数量小于100的时候我们就给它的cnt100标记为1,每当一颗树上苹果数量小于10的时候,我们就给它的used标记为true,表示当前结点不能再摘苹果了。然后我们用pushup上传信息即可。

#include <iostream>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <stack>
#include <queue>
#include <numeric>
#include <cassert>
#include <bitset>
#include <cstdio>
#include <vector>
#include <unordered_set>
#include <cmath>
#include <map>
#include <unordered_map>
#include <set>
#include <deque>
#include <tuple>
#include <array>
 
#define all(a) a.begin(), a.end()
#define cnt0(x) __builtin_ctz(x)
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define cntone(x) __builtin_popcount(x)
#define db double
#define fs first
#define ls(x) (tr[x].l)
#define rs(x) (tr[x].r)
#define cnt(x) (tr[x].cnt)
#define mx(x) (tr[x].v)
#define se second
#define AC main(void)
#define HYS std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
typedef std::pair<int, int > PII;
typedef std::pair<int, std::pair<int, int>> PIII;
typedef std::pair<ll, ll> Pll;
typedef std::pair<double, double> PDD;
using ld = double long;

const long double eps = 1e-9;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 10, M = 4e5 + 10;
int n , m, p;

int d1[] = {0, 0, 1, -1};
int d2[] = {1, -1, 0, 0};

int a[N];

struct node{
	int l, r;
	ll sum;
	int cnt100, used;//小于100的数量,
}tr[N << 2];

inline void pushup(int u){
	if(tr[u << 1].used && tr[u << 1 | 1].used)	tr[u].used = true;
	tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
	tr[u].cnt100 = tr[u << 1].cnt100 + tr[u << 1 | 1].cnt100;
}

inline void build_tree(int u, int l, int r){
	tr[u] = {l, r};
	if(l == r){
		tr[u].sum = a[l];
		if(a[l] < 100)	tr[u].cnt100 = 1;
		if(a[l] < 10)	tr[u].used = true;
		return ;
	}
	int mid = l + r >> 1;
	build_tree(u << 1, l, mid);
	build_tree(u << 1 | 1, mid + 1, r);
	pushup(u);
}

inline void modify(int u, int l, int r){
	if(tr[u].used)	return ;
	if(tr[u].l == tr[u].r){
		tr[u].sum -= (tr[u].sum + 2) / 3;
		if(tr[u].sum < 100)	tr[u].cnt100 = 1;
		if(tr[u].sum < 10)	tr[u].used = true;
		return ;
	}
	int mid = tr[u].l + tr[u].r >> 1;
	if(l <= mid)	modify(u << 1, l, r);
	if(r > mid)	modify(u << 1 | 1, l, r);
	pushup(u);
}

inline int query100(int u, int l, int r){
	if(tr[u].l >= l && tr[u].r <= r)	return tr[u].cnt100;
	int res = 0;
	int mid = tr[u].l + tr[u].r >> 1;
	if(l <= mid)	res += query100(u << 1, l, r);
	if(r > mid)	res += query100(u << 1 | 1, l, r);
	return res;
}

inline ll querysum(int u, int l, int r){
	if(tr[u].l >= l && tr[u].r <= r)	return tr[u].sum;
	ll res = 0;
	int mid = tr[u].l + tr[u].r >> 1;
	if(l <= mid)	res += querysum(u << 1, l, r);
	if(r > mid)	res += querysum(u << 1 | 1, l, r);
	return res;
}

inline void solve(){
	std::cin >> n >> m;
	for(int i = 1; i <= n; i ++)	std::cin >> a[i];
	build_tree(1, 1, n);
	for(int i = 1; i <= m; i ++){
		int op, l, r;
		std::cin >> op >> l >> r;
		if(op == 1){
			modify(1, l, r);
		}else if(op == 2){
			std::cout << query100(1, l, r) << '\n';
		}else{
			std::cout << querysum(1, l, r) << '\n';
		}
	}
}

signed AC{
   	HYS
   	
	int _ = 1;
	//std::cin >> _;
	while(_ --)
        solve();

    return 0;
}

最后放一道很像的,也不知道没买牛客集训的能不能写

#include <iostream>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <stack>
#include <queue>
#include <numeric>
#include <cassert>
#include <bitset>
#include <cstdio>
#include <vector>
#include <unordered_set>
#include <cmath>
#include <map>
#include <unordered_map>
#include <set>
#include <deque>

using namespace std;

#define all(a) a.begin(), a.end()
#define cnt0(x) __builtin_ctz(x)
#define endl '\n'
#define itn int
#define ll long long
#define ull unsigned long long
#define rep(i, a, b) for(int i = a;i <= b; i ++)
#define per(i, a, b) for(int i = a;i >= b; i --)
#define cntone(x) __builtin_popcount(x)
#define db double
#define x first
#define y second
#define AC main(void)
#define HYS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
typedef pair<int, int > PII;
typedef pair<int, pair<int, int>> PIII;
typedef pair<ll, ll> Pll;
typedef pair<double, double> PDD;
using ld = double long;

const int MOD = 998244353;
const double eps = 1e-8;

const int N = 1e3 + 10, M = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int n, m;
int _ = 1;
int res;
int d1[] = {0, 0, 1, -1};
int d2[] = {1, -1, 0, 0};
int a[M];

struct node{
	int l, r;
	ll v;
	ll lazy;
	int tar, keep;
}tr[M * 4];

void pushup(int u){
	tr[u].v = tr[u << 1].v + tr[u << 1 | 1].v;
	if(tr[u << 1].keep && tr[u << 1 | 1].keep)	tr[u].keep = 1;
}

void pushdown(int u){
	if(tr[u].lazy){
		tr[u].tar = 0;
		tr[u << 1 | 1].tar = tr[u << 1].tar = 1;
		tr[u << 1].lazy += tr[u].lazy;
		tr[u << 1 | 1].lazy += tr[u].lazy;
		tr[u].lazy = 0;
	}
}

int sswr(int x){
	double t = sqrt(x);
	t *= 10;
	int tt = t * 10;
	if(tt % 10 >= 5)	return (int)t + 1;
	else return (int)t; 
}

void build_tree(int u, int l, int r){
	tr[u] = {l, r};
	tr[u].keep = 0;
	if(l == r){
		tr[u].v = a[l]; 
		return ;
	}	
	int mid = l + r >> 1;
	build_tree(u << 1, l, mid);
	build_tree(u << 1 | 1, mid + 1, r);
	pushup(u);
}

void modify(int u, int l, int r, int k){
	if(tr[u].keep)	return ;
	tr[u].tar = 1;
	if(tr[u].l >= l && tr[u].r <= r){
		tr[u].lazy += k;
		return ;
	}
	int mid = tr[u].l + tr[u].r >> 1;
	if(l <= mid)	modify(u << 1, l, r, k);
	if(r > mid)	modify(u << 1 | 1, l, r, k);
}

ll query(int u, int l, int r){
	if(!tr[u].tar || tr[u].keep)	return tr[u].v;
	tr[u].tar = 0;
	if(tr[u].l == tr[u].r){
		int last = tr[u].v;
		int k = tr[u].lazy;
		while(k --){
			int now = sswr(last);
			if(now == last){
				tr[u].keep = 1;
				break;
			}
			last = now;
		}
		tr[u].lazy = 0;
		tr[u].v = last;
		return tr[u].v;
	}
	pushdown(u);
	ll sum = 0;
	int mid = tr[u].l + tr[u].r >> 1;
	sum = query(u << 1, l, r);
	sum += query(u << 1 | 1, l, r);
	pushup(u);
	return sum;
}

void solve(){
	cin >> n >> m;
	for(int i = 1; i <= n; i ++)	cin >> a[i];
	build_tree(1, 1, n);
	while(m --){
		int op;
		cin >> op;
		if(op == 2)	cout << query(1, 1, n) << endl;
		else{
			int l, r, k;
			cin >> l >> r >> k;
			modify(1, l, r, k);
		}
	}
}

int AC{
    HYS
    
	//cin >> _;
	while(_ --)
        solve();
    
    return 0;
}
posted @ 2023-03-16 19:01  春始于雪之下  阅读(33)  评论(0编辑  收藏  举报