Turing Tree HDU - 3333

 

点击打开链接

 

两种做法

线段树离线处理 将查询区间右端点升序排序 然后依次遍历

每个数的值只体现在已经遍历过的序列范围内最靠右的位置 用map记录数的位置 线段树更新和查询

#include <bits/stdc++.h>
using namespace std;
#define ll long long

struct node1
{
    ll ans;
    int l;
    int r;
    int id;
};

struct node2
{
    ll val;
    int l;
    int r;
};

map <int,int> mp;
node1 pre[100010];
node2 tree[120010];
ll num[30010];
int n;

bool cmpI(node1 n1,node1 n2)
{
    return n1.r<n2.r;
}

bool cmpII(node1 n1,node1 n2)
{
    return n1.id<n2.id;
}

void pushup(int cur)
{
    tree[cur].val=tree[cur*2].val+tree[cur*2+1].val;
    return;
}

void build(int l,int r,int cur)
{
    int m;
    tree[cur].val=0;
    tree[cur].l=l;
    tree[cur].r=r;
    if(l==r) return;
    m=(l+r)/2;
    build(l,m,cur*2);
    build(m+1,r,cur*2+1);
    return;
}

void update(int tar,ll val,int cur)
{
    if(tree[cur].l==tree[cur].r)
    {
        tree[cur].val+=val;
        return;
    }
    if(tar<=tree[cur*2].r) update(tar,val,cur*2);
    else update(tar,val,cur*2+1);
    pushup(cur);
    return;
}

ll query(int pl,int pr,int cur)
{
    ll res;
    if(pl<=tree[cur].l&&tree[cur].r<=pr)
    {
        return tree[cur].val;
    }
    res=0;
    if(pl<=tree[cur*2].r) res+=query(pl,pr,cur*2);
    if(pr>=tree[cur*2+1].l) res+=query(pl,pr,cur*2+1);
    return res;
}

int main()
{
    int t,q,i,j,p;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        mp.clear();
        build(1,n,1);
        for(i=1;i<=n;i++)
        {
            scanf("%lld",&num[i]);
        }
        scanf("%d",&q);
        for(i=1;i<=q;i++)
        {
            scanf("%d%d",&pre[i].l,&pre[i].r);
            pre[i].id=i;
        }
        sort(pre+1,pre+q+1,cmpI);
        p=1;
        for(i=1;i<=q;i++)
        {
            while(p<=pre[i].r)
            {
                if(mp[num[p]]!=0)
                {
                    update(mp[num[p]],-num[p],1);
                }
                mp[num[p]]=p;
                update(p,num[p],1);
                p++;
            }
            pre[i].ans=query(pre[i].l,pre[i].r,1);
        }
        sort(pre+1,pre+q+1,cmpII);
        for(i=1;i<=q;i++)
        {
            printf("%lld\n",pre[i].ans);
        }
    }
    return 0;
}

 

主席树也有两种写法 详见代码 还是所有数都尽量向一侧靠拢 还有HDU上交G++会RE到死

#include <cstdio>
#include <map>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long

struct node
{
    int l;
    int r;
    ll val;
};

map <ll,int> mp;
node tree[1000010];
ll ary[30010];
int root[30010];
int n,q,num;

int build(int l,int r)
{
    int cur,m;
    cur=num++;
    tree[cur].l=0,tree[cur].r=0,tree[cur].val=0;
    if(l==r) return cur;
    m=(l+r)/2;
    tree[cur].l=build(l,m);
    tree[cur].r=build(m+1,r);
    return cur;
}

int update(int rot,int tar,ll val,int l,int r)
{
    int cur,m;
    cur=num++;
    tree[cur]=tree[rot];
    tree[cur].val+=val;
    if(l==r) return cur;
    m=(l+r)/2;
    if(tar<=m) tree[cur].l=update(tree[rot].l,tar,val,l,m);
    else tree[cur].r=update(tree[rot].r,tar,val,m+1,r);
    return cur;
}

ll query(int rot,int pl,int pr,int l,int r)
{
    ll res;
    int m;
    if(pl<=l&&r<=pr)
    {
        return tree[rot].val;
    }
    res=0,m=(l+r)/2;
    if(pl<=m) res+=query(tree[rot].l,pl,pr,l,m);
    if(pr>=m+1) res+=query(tree[rot].r,pl,pr,m+1,r);
    return res;
}

int main()
{
    int t,i,l,r;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%lld",&ary[i]);
        }
        mp.clear();
        num=0;
        root[0]=build(1,n);
        for(i=1;i<=n;i++)
        {
            if(mp[ary[i]]!=0)
            {
                root[i]=update(root[i-1],mp[ary[i]],-ary[i],1,n);
                root[i]=update(root[i],i,ary[i],1,n);
            }
            else
            {
                root[i]=update(root[i-1],i,ary[i],1,n);
            }
            mp[ary[i]]=i;
        }
        scanf("%d",&q);
        while(q--)
        {
            scanf("%d%d",&l,&r);
            printf("%lld\n",query(root[r],l,r,1,n));
        }
    }
    return 0;
}

 

#include <cstdio>
#include <map>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=3e4+10;

struct node
{
	ll val;
	int l,r;
};

map <ll,int> mp;
node tree[20*maxn];
int root[maxn];
int n,q,num;

int build(int l,int r)
{
	int cur,m;
	cur=num++;
	tree[cur].l=tree[cur].r=tree[cur].val=0;
	if(l==r) return cur;
	m=(l+r)/2;
	tree[cur].l=build(l,m);
	tree[cur].r=build(m+1,r);
	return cur;
}

int update(int rot,int tar,ll val,int l,int r)
{
	int cur,m;
	cur=num++;
	tree[cur]=tree[rot];
	tree[cur].val+=val;
	if(l==r) return cur;
	m=(l+r)/2;
	if(tar<=m) tree[cur].l=update(tree[rot].l,tar,val,l,m);
	else tree[cur].r=update(tree[rot].r,tar,val,m+1,r);
	return cur;
}

ll query(int lrot,int rrot,int pl,int pr,int l,int r)
{
	ll res;
	int m;
	if(pl<=l&&r<=pr){
		return tree[rrot].val-tree[lrot].val;
	}
	res=0,m=(l+r)/2;
	if(pl<=m) res+=query(tree[lrot].l,tree[rrot].l,pl,pr,l,m);
	if(pr>m) res+=query(tree[lrot].r,tree[rrot].r,pl,pr,m+1,r);
	return res;
}

int main()
{
	ll val;
	int t,i,l,r;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		mp.clear();
		num=0;
		root[0]=build(0,n-1);
		for(i=1;i<=n;i++){
			scanf("%lld",&val);
			root[i]=update(root[i-1],mp[val],val,0,n-1);
			mp[val]=i;
		}
		scanf("%d",&q);
		while(q--){
			scanf("%d%d",&l,&r);
			printf("%lld\n",query(root[l-1],root[r],0,l-1,0,n-1));
		}
	}
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值