线段树练习

A - Lost Cows

#include<iostream>
#include<stdio.h>
#include<cmath>
using namespace std;

const int MAX = 10000;
int pre[MAX], tree[4*MAX], ans[MAX];

void BuildTree(int n, int last_left){
    int i;
    for(i=last_left; i<last_left+n; i++){
        tree[i] = 1;
    }
    while(last_left != 1){
        for(i=last_left/2; i<last_left; i++){
            tree[i] = tree[2*i] + tree[2*i+1];
        }
        last_left = last_left/2;
    }
}

int query(int u, int num, int last_left){
    tree[u]--;
    if(tree[u]==0 && u>=last_left){
        return u;
    }
    if(tree[u<<1]<num) return query((u<<1)+1, num-tree[u<<1], last_left);
    else return query(u<<1, num, last_left);
}

int main(){
    int n, last_left, i;
    scanf("%d", &n);
    pre[1] = 0;

    last_left = 1<<(int(log(n)/log(2))+1);

    for(i=2; i<=n; i++) scanf("%d", &pre[i]);

    BuildTree(n, last_left);

    for(i=n; i>=1; i--) ans[i] = query(1, pre[i]+1, last_left) - last_left + 1;

    for(i=1; i<=n; i++) printf("%d\n", ans[i]);

    return 0;
}

C - A Simple Problem with Integers

 

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
ll a[100010];
struct z
{
    ll l,r,sum,lazy;
}tree[100010*4];
void pushdown(ll x)
{
    if(tree[x].lazy)
    {
        tree[2*x].lazy+=tree[x].lazy;
        tree[2*x+1].lazy+=tree[x].lazy;
        tree[x*2].sum+=tree[x].lazy*(tree[x*2].r-tree[x*2].l+1);
        tree[x*2+1].sum+=tree[x].lazy*(tree[x*2+1].r-tree[x*2+1].l+1);
        tree[x].lazy=0;
    }
}
void build(ll l,ll r,ll k)
{
    tree[k].l=l;
    tree[k].r=r;
    tree[k].lazy=0;
    if(l==r)
    {
        tree[k].sum=a[r];
        return;
    }
    ll mid=(l+r)/2;
    build(l,mid,k*2);
    build(mid+1,r,k*2+1);
    tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
}
void add(ll l,ll r,ll v,ll k)
{
    if(l<=tree[k].l&&r>=tree[k].r)
    {
        tree[k].sum+=v*(tree[k].r-tree[k].l+1);
        tree[k].lazy+=v;
        return;
    }
    pushdown(k);
    ll mid=(tree[k].l+tree[k].r)/2;
    if(l<=mid)
    add(l,r,v,k*2);
    if(r>mid)
    add(l,r,v,k*2+1);
    tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
}
ll query(ll l,ll r,ll k)
{
    if(l<=tree[k].l&&r>=tree[k].r)
    return tree[k].sum;
    pushdown(k);
    ll mid=(tree[k].l+tree[k].r)/2,ans=0;
    if(l<=mid)
    ans+=query(l,r,k*2);
    if(r>mid)
    ans+=query(l,r,k*2+1);
    return ans;
}
int main()
{
    ll n,m;
    while(~scanf("%lld%lld",&n,&m))
    {
        ll x,y,z,i,j;
        char r;
        for(i=1;i<=n;i++)
        scanf("%lld",&a[i]);
        build(1,n,1);
        while(m--)
        {
            getchar();
            scanf("%c",&r);
            if(r=='C')
            {
            	scanf("%lld%lld%lld",&x,&y,&z);
                add(x,y,z,1);   
            }
            else
            {
                scanf("%lld%lld",&x,&y);
                printf("%lld\n",query(x,y,1));
            }
        }
    }
    return 0;
}

A - 线段树 2 

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
int n,m,a[1000005],mod;
struct node{
	ll sum,l,r,mu,add;
}t[1000005];
ll read(){
	ll x=0;char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x;
}
void build(ll p,ll l,ll r){
	t[p].l=l,t[p].r=r;t[p].mu=1;
	if(l==r){t[p].sum=a[l]%mod;return ;}
	ll mid=(l+r)>>1;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	t[p].sum=(t[p*2].sum+t[p*2+1].sum)%mod;
}
void spread(ll p){
    t[p*2].sum=(ll)(t[p].mu*t[p*2].sum+((t[p*2].r-t[p*2].l+1)*t[p].add)%mod)%mod;
    t[p*2+1].sum=(ll)(t[p].mu*t[p*2+1].sum+(t[p].add*(t[p*2+1].r-t[p*2+1].l+1))%mod)%mod;//add已经乘过mu啦
	
    t[p*2].mu=(ll)(t[p*2].mu*t[p].mu)%mod;
    t[p*2+1].mu=(ll)(t[p*2+1].mu*t[p].mu)%mod;

	t[p*2].add=(ll)(t[p*2].add*t[p].mu+t[p].add)%mod;
    t[p*2+1].add=(ll)(t[p*2+1].add*t[p].mu+t[p].add)%mod;
    
    t[p].mu=1,t[p].add=0;
}
void add(ll p,ll l,ll r,ll k){
	if(t[p].l>=l&&t[p].r<=r){
		t[p].add=(t[p].add+k)%mod;
		t[p].sum=(ll)(t[p].sum+k*(t[p].r-t[p].l+1))%mod;//只要加上增加的就好
		return ;
	}
	spread(p);
	t[p].sum=(t[p*2].sum+t[p*2+1].sum)%mod;
	ll mid=(t[p].l+t[p].r)>>1;
	if(l<=mid)add(p*2,l,r,k);
	if(mid<r)add(p*2+1,l,r,k);
	t[p].sum=(t[p*2].sum+t[p*2+1].sum)%mod;
	
}
void mu(ll p,ll l,ll r,ll k){
	if(t[p].l>=l&&t[p].r<=r){
		t[p].add=(t[p].add*k)%mod;//比较重要的一步,add要在这里乘上k,因为后面可能要加其他的数而那些数其实是不用乘k的
		t[p].mu=(t[p].mu*k)%mod;
		t[p].sum=(t[p].sum*k)%mod;
		return ;
	}
	spread(p);
    t[p].sum=t[p*2].sum+t[p*2+1].sum;
	ll mid=(t[p].l+t[p].r)>>1;
	if(l<=mid)mu(p*2,l,r,k);
	if(mid<r)mu(p*2+1,l,r,k);
	t[p].sum=(t[p*2].sum+t[p*2+1].sum)%mod;
}
ll ask(ll p,ll l,ll r){
	if(t[p].l>=l&&t[p].r<=r){
		return t[p].sum;
	}
	spread(p);
	ll val=0;
	ll mid=(t[p].l+t[p].r)>>1;
	if(l<=mid)val=(val+ask(p*2,l,r))%mod;
	if(mid<r)val=(val+ask(p*2+1,l,r))%mod;
	return val;
}
int main(){
	cin>>n>>m>>mod;
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	build(1,1,n);
	for(int i=1;i<=m;i++){
		int ty=read();
		if(ty==1){
			ll cn=read(),cm=read(),cw=read();
			mu(1,cn,cm,cw);
		}else if(ty==2){
			ll cn=read(),cm=read(),cw=read();
			add(1,cn,cm,cw);
		}else {
			ll cn=read(),cm=read();
			cout<<ask(1,cn,cm)<<endl;
		}
    }
}

 

D - Just a Hook

 

#include<iostream>
typedef long long ll;
using namespace std;
const int N=100000;
int a[N];
struct 	node{
	ll l,r,sum,lazy;
}tr[N*4];
void pushup(int h){
	tr[h].sum=tr[h*2].sum+tr[h*2+1].sum;
}
void pushdown(int u) { //  破坏了 u节点的区间一致性, 将还未往下分发的值向下分发 
	if(!tr[u].lazy) {
		return;
	}
	tr[u * 2].lazy = tr[u].lazy;
	tr[u * 2 + 1].lazy = tr[u].lazy;
	tr[u * 2].sum = (tr[u * 2].r - tr[u * 2].l + 1) * tr[u].lazy;
	tr[u * 2 + 1].sum =(tr[u * 2 + 1].r - tr[u * 2 + 1].l + 1) * tr[u].lazy;
	tr[u].lazy = 0;
}
void build(int h,int l,int r){
	if(l==r){
		tr[h]={l,r,a[l]};
		return ;
	}
	tr[h]={l,r};
	int mid=(l+r)/2;
	build(h*2,l,mid);
	build(h*2+1,mid+1,r);
	pushup(h);
}
void mod(int h,int x,int y,int k){
	if(tr[h].l>=x&&tr[h].r<=y){
		tr[h].lazy=k;
		tr[h].sum = (tr[h].r-tr[h].l+1)*k;
		return ;
	}
	if(tr[h].l>y||tr[h].r<x){
		return ;		
	}
	int mid=(tr[h].l+tr[h].r)/2;
	pushdown(h);
	if(mid>=x)
	mod(h*2,x,y,k);
	if(mid<y)
	mod(h*2+1,x,y,k);
	pushup(h);
}
ll que(int h,int x,int y){
	if(tr[h].l>=x&&tr[h].r<=y){
		return tr[h].sum;
	}
	if(tr[h].l>y||tr[h].r<x){
		return 0;		
	}
	pushdown(h);
	ll s=0;
	int mid=(tr[h].l+tr[h].r)/2;
	if(mid>=x)
	s+=que(h*2,x,y);
	if(mid<y)
	s+=que(h*2+1,x,y);
	return s;
}
int main()
{
	int T;
	ll cnt=0;
	scanf("%d",&T);
	while(T--){
		cnt++;
		int n,m;
		scanf("%d",&n);
		for(int i=1 ; i<=n ; i++){
			a[i]=1;
		}
		build(1,1,n);
		scanf("%d",&m);
		while(m--){
			int x,y,k;
			scanf("%d %d %d",&x,&y,&k);
			mod(1,x,y,k);	
		}
			printf("Case %lld: The total value of the hook is %lld.\n",cnt,que(1,1,n));
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值