https://codeforces.com/gym/102770/problem/E
给一个dp转移式子,求dp[m][k] m=r-l+1
dp不是玄学吗?
话说给我了一个式子,我直接转不就好了,发现n<1e5,那算了
分析一个小例子发现
前面式子用循环求或者公式,后面维护区间前k之和即可
主席树板子
记得io优化,开ll,还有多组样例,主席树清空
// Problem: E. Easy DP Problem
// Contest: Codeforces - The 17th Zhejiang Provincial Collegiate Programming Contest
// URL: https://codeforces.com/gym/102770/problem/E
// Memory Limit: 512 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<iostream>
#include<algorithm>
#include<vector>
#define INF 1e6
using namespace std;
typedef long long ll;
const int N=1e5+9;
int a[N];
vector<int> X;
//主席树
ll binary(int x){
return lower_bound(X.begin(),X.end(),x)-X.begin()+1;
}
struct ZXSEG{
struct node{
int l,r;//左右儿子,关系
int s;//节点值域中有多少个数
ll sum;
ll val;
}seg[N*22];//n*(logn*3);logn+3向上取整
#define tl(id) seg[id].l//宏定义简洁
#define tr(id) seg[id].r
int root[N],index;//根节点,节点数量
void reset(int n){
for(int i=1;i<=n;i++){
root[i]=0;
}
index=0;
}
void build(int &id,int l,int r){//传引用,通过子空间id值给父空间的gx[0],gx[1]赋值
id=++index;
if(l==r){
return;
}
int mid=(l+r)>>1;
build(tl(id),l,mid);
build(tr(id),mid+1,r);
}
/*
递归建立各个历史版本的线段树
post是前一个版本的节点指针,curr是当前版本的节点指针
curr是传引用,通过子空间curr值,给父空间的tl(curr),tr(curr)赋值
*/
void insert(int post,int &curr,int l,int r,int v){
curr=++index;//开新节点
seg[curr]=seg[post];//赋值
seg[curr].s++;//更新
seg[curr].sum+=X[v-1];
if(l==r){
seg[curr].val=X[v-1];
return;
}
int mid=(l+r)>>1;
if(v<=mid){//在左边递归
insert(tl(post),tl(curr),l,mid,v);
}else{
insert(tr(post),tr(curr),mid+1,r,v);
}
}
/*
找区间[l,r]内的第k小,插入r的历史版本,进行二分
[l,r]==[1,r]-[1,l-1];
*/
ll query(int post,int curr,int l,int r,ll k){
if(l==r){//
return seg[curr].val*k;
}
int mid=(l+r)>>1;
int s=seg[tr(curr)].s-seg[tr(post)].s;//变化信息
if(k<=s){//找k的位置
return query(tr(post),tr(curr),mid+1,r,k);
}else{
return seg[tr(curr)].sum-seg[tr(post)].sum+query(tl(post),tl(curr),l,mid,k-s);//减去左边的
}
}
}t;
void solve(){
int n;
cin>>n;
X.clear();
t.reset(n);
for(int i=1;i<=n;i++){
cin>>a[i];
X.push_back(a[i]);
}
sort(X.begin(),X.end());
X.erase(unique(X.begin(),X.end()),X.end());
int xn=X.size();
t.build(t.root[0],1,xn);
for(int i=1;i<=n;i++){
t.insert(t.root[i-1],t.root[i],1,xn,binary(a[i]));
}
int q;
cin>>q;
for(int i=1;i<=q;i++){
int l,r,k;
cin>>l>>r>>k;
ll m=(r-l+1);
ll t1=m*(m+1ll)*(2ll*m+1ll);
t1/=6ll;
ll t2=t.query(t.root[l-1],t.root[r],1,xn,k);
ll ans=t1+t2;
cout<<ans<<'\n';
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}