求区间内小于等于x的值之和
1.动态开点+主席树
好写维护一下区间和就好了
2.离散化+主席树
常数小
3.分块维护区间和以及有序,散块暴力,整块二分找位置
code
一。
// LUOGU_RID: 170820941
// Problem: G - Smaller Sum
// Contest: AtCoder - Japan Registry Services (JPRS) Programming Contest 2024 (AtCoder Beginner Contest 339)
// URL: https://atcoder.jp/contests/abc339/tasks/abc339_g
// Memory Limit: 1024 MB
// Time Limit: 3500 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll;
constexpr int MX=1e9;
const int N=2e5+9;
int a[N];
//主席树
struct ZXSEG{
struct node{
int l,r;//左右儿子,关系
ll sum;
}seg[N*100];//n*(logn*3);logn+3向上取整
#define tl(id) seg[id].l//宏定义简洁
#define tr(id) seg[id].r
int root[N],index;//根节点,节点数量
bool inrange(int L,int R,int l,int r){return L>=l && R<=r;}
bool outofrange(int L,int R,int l,int r){return l>R || L>r;}
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){
seg[curr=++index]=seg[post];//赋值
seg[curr].sum+=v;//更新
if(l==r){
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,int l,int r){
if(inrange(L,R,l,r)){
return seg[curr].sum-seg[post].sum;
}else if(!outofrange(L,R,l,r)){
int mid=(L+R)>>1;
return query(tl(post),tl(curr),L,mid,l,r)+query(tr(post),tr(curr),mid+1,R,l,r);
}else{
return 0;
}
}
}t;
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
t.insert(t.root[i-1],t.root[i],0,MX,a[i]);
}
int q;
cin>>q;
ll ans=0;
for(int i=1;i<=q;i++){
ll l,r,x;
cin>>l>>r>>x;
l^=ans,r^=ans,x^=ans;
if(l>r){
swap(l,r);
}
cout<<(ans=t.query(t.root[l-1],t.root[r],0,MX,0,x))<<'\n';
}
return 0;
return 0;
}
二.
// LUOGU_RID: 170822545
// Problem: G - Smaller Sum
// Contest: AtCoder - Japan Registry Services (JPRS) Programming Contest 2024 (AtCoder Beginner Contest 339)
// URL: https://atcoder.jp/contests/abc339/tasks/abc339_g
// Memory Limit: 1024 MB
// Time Limit: 3500 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=2e5+9;
vector<int> X;
int a[N];
//主席树
struct ZXSEG{
struct node{
int l,r;//左右儿子,关系
ll sum;
}seg[N<<5];//动态开点
#define tl(id) seg[id].l//宏定义简洁
#define tr(id) seg[id].r
int root[N],index;//根节点,节点数量
bool inrange(int L,int R,int l,int r){return L>=l && R<=r;}
bool outofrange(int L,int R,int l,int r){return l>R || L>r;}
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){
seg[curr=++index]=seg[post];//赋值
seg[curr].sum+=X[v-1];//更新
if(l==r){
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 ask(int post,int curr,int l,int r,int k){//区间k
if(l==r){//
return l;
}
int mid=(l+r)>>1;
int s=seg[tl(curr)].sum-seg[tl(post)].sum;//变化信息
if(k<=s){//找k的位置
return ask(tl(post),tl(curr),l,mid,k);
}else{
return ask(tr(post),tr(curr),mid+1,r,k-s);//减去左边的
}
}
ll query(int post,int curr,int L,int R,int l,int r){//求0-x的和
if(inrange(L,R,l,r)){
return seg[curr].sum-seg[post].sum;
}else if(!outofrange(L,R,l,r)){
int mid=(L+R)>>1;
return query(tl(post),tl(curr),L,mid,l,r)+query(tr(post),tr(curr),mid+1,R,l,r);
}else{
return 0;
}
}
}t;
ll binary(ll x){return lower_bound(X.begin(),X.end(),x)-X.begin()+1;}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n;
cin>>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();
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;
ll ans=0;
for(int i=1;i<=q;i++){
ll l,r,x;
cin>>l>>r>>x;
l^=ans,r^=ans,x^=ans;
x=upper_bound(X.begin(),X.end(),x)-X.begin();
cout<<(ans=t.query(t.root[l-1],t.root[r],1,xn,1,x))<<'\n';
}
return 0;
}
三.
// LUOGU_RID: 170829733
// Problem: G - Smaller Sum
// Contest: AtCoder - Japan Registry Services (JPRS) Programming Contest 2024 (AtCoder Beginner Contest 339)
// URL: https://atcoder.jp/contests/abc339/tasks/abc339_g
// Memory Limit: 1024 MB
// Time Limit: 3500 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=2e5+9;
int a[N];
struct BLOCK{
//每个块的范围,[l,r]属于那个块
int L[N],R[N],pos[N];
//一个块的信息
vector<ll> prefix[N];
vector<int> v[N];
int t=0;
void init(int n){
t=sqrt(n);
for(int i=1;i<=t;i++){
L[i]=(i-1)*t+1;
R[i]=i*t;
}
if(R[t]<n){
t++;
L[t]=R[t-1]+1;
R[t]=n;
}
for(int i=1;i<=t;i++){
for(int j=L[i];j<=R[i];j++){
pos[j]=i;
}
}
for(int i=1;i<=t;i++){
for(int j=L[i];j<=R[i];j++){
v[i].push_back(a[j]);
}
}
for(int i=1;i<=t;i++){
sort(v[i].begin(),v[i].end());
}
for(int i=1;i<=t;i++){
ll t=0;
prefix[i].push_back(t);
for(auto & x : v[i]){
prefix[i].push_back(t+=x);
}
}
// for(int i=1;i<=t;i++){
// for(auto & x : v[i]){
// cout<<x<<" ";
// }
// cout<<'\n';
// }
// cout<<'\n';
// cout<<'\n';
// cout<<'\n';
// cout<<'\n';
// for(int i=1;i<=t;i++){
// for(auto & x : prefix[i]){
// cout<<x<<" ";
// }
// cout<<'\n';
// }
}
ll query(ll l,ll r,ll x){
int p=pos[l];
int q=pos[r];
ll res=0;
if(p==q){
for(int i=l;i<=r;i++){
if(a[i]<=x){
res+=a[i];
}
}
}else{
for(int i=l;i<=R[p];i++){
if(a[i]<=x){
res+=a[i];
}
}
for(int i=p+1;i<=q-1;i++){
int p=upper_bound(v[i].begin(),v[i].end(),x)-v[i].begin();
// cout<<"sadasdadad"<<" "<<p<<'\n';
if(!p){
continue;
}else{
res+=prefix[i][p];
}
}
for(int i=L[q];i<=r;i++){
if(a[i]<=x){
res+=a[i];
}
}
}
return res;
}
}blo;
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
blo.init(n);
// for(int i=1;i<=n;i++){
// cout<<blo.prefix[i]<<" ";
// }
// cout<<'\n';
int q;
cin>>q;
ll ans=0;
for(int i=1;i<=q;i++){
ll l,r,x;
cin>>l>>r>>x;
l^=ans,r^=ans,x^=ans;
// cout<<l<<' '<<r<<' '<<" "<<x<<'\n';
cout<<(ans=blo.query(l,r,x))<<'\n';
}
return 0;
}