2020浙江省赛E Easy DP Problem(主席树板子题)

Login - Codeforces (Unofficial mirror site, accelerated for Chinese users)

(题目链接)

题意 : 求[l, r]区间的前k大和

#include<iostream>
#include<algorithm>
#include<string> 
#include<set> 
#include<map>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<unordered_map>
#include<iomanip>
#define ll long long
#define ull unsigned long long
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
#define m_p make_pair
#define pi acos(-1)
using namespace std;

const int N = 1e5 + 5;
const double eps = 1e-4;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
//const ll mod = 1000003;
inline ll qpow(ll x, ll y, ll M){ll ans=1;while(y){if(y&1)ans=ans*x%M;x=x*x%M;y=y>>1;}return ans;}
inline ll gcd(ll x, ll y){return y?gcd(y,x%y):x;}

ll n, m, a[N], num;

struct node{
	ll ls, rs, sum, anssum;
}tree[N<<5]; 
ll rt[N], sz;

void update(ll l, ll r, ll &x, ll y, ll p)
{
	x = ++sz;
	tree[x] = tree[y];
	tree[x].sum++;
	tree[x].anssum += p;
	if(l == r)
		return;
	ll mid = (l + r) >> 1;
	if(p <= mid)
		update(l, mid, tree[x].ls, tree[y].ls, p);
	else
		update(mid + 1, r, tree[x].rs, tree[y].rs, p);
}

ll query(ll l, ll r, ll x, ll y, ll k)
{
	ll temp = tree[tree[y].rs].sum - tree[tree[x].rs].sum;
	ll ansr = tree[tree[y].rs].anssum - tree[tree[x].rs].anssum;
	if(l == r)
		return l * k;//此处k相当于值为l的数量
	ll mid = (l + r) >> 1;
	if(temp == k)
		return ansr;
	else if(temp < k)
		return ansr + query(l, mid, tree[x].ls, tree[y].ls, k - temp);
	else
		return query(mid+1, r, tree[x].rs, tree[y].rs, k);
}

void solve()
{
	sz = 0;
	cin>>n;
	for(ll i = 1; i <= n; i++)
	{
		cin>>a[i];
		update(1, 1000000, rt[i], rt[i-1], a[i]);	
	}	
	cin>>m;
	while(m--)
	{
		ll l, r, k;
		cin>>l>>r>>k;
		ll len = r - l + 1;
		cout<<query(1, 1000000, rt[l-1], rt[r], k) + len * (len + 1) * (2 * len + 1) / 6<<'\n'; 
	}
} 

signed main()
{
	IOS;
	//init();
	ll t = 1;
	cin>>t;
	while(t--)
		solve();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值