G - Smaller Sum

G - Smaller Sum

求区间内小于等于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;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
To solve this problem, we can follow the following steps: 1. Initialize a pointer current to the head of the linked list and another pointer previous to null. 2. Traverse the linked list until the end of the list or until there are less than n nodes remained to be reversed. 3. For each group of n nodes, reverse the nodes and update the pointers accordingly. 4. If there are less than n nodes remaining, reverse them as well. 5. Return the updated head of the linked list. Here is the Python code that implements the above algorithm: ```python class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def reverseLinkedList(head, n): current = head previous = None while current: last_node_of_previous_part = previous last_node_of_sub_list = current i = 0 while current and i < n: next_node = current.next current.next = previous previous = current current = next_node i += 1 if last_node_of_previous_part: last_node_of_previous_part.next = previous else: head = previous last_node_of_sub_list.next = current previous = last_node_of_sub_list return head ``` Here is an example usage of the above function: ```python # create input linked list: A -> B -> C -> D -> E -> F -> G -> H -> I a = ListNode("A") b = ListNode("B") c = ListNode("C") d = ListNode("D") e = ListNode("E") f = ListNode("F") g = ListNode("G") h = ListNode("H") i = ListNode("I") a.next = b b.next = c c.next = d d.next = e e.next = f f.next = g g.next = h h.next = i # reverse the linked list in groups of 3 nodes head = reverseLinkedList(a, 3) # print the updated linked list: A -> D -> C -> B -> G -> F -> E -> I -> H current = head while current: print(current.val, end=" -> ") current = current.next print("None") ``` Output: ``` A -> D -> C -> B -> G -> F -> E -> I -> H -> None ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值