zoukankan      html  css  js  c++  java
  • 利用主席树 搞区间不同值的和

    #include<iostream>
    #include<vector>
    #include<cstdio>
    #include<map>
    #include<algorithm> 
    using namespace std;
    typedef long long ll;
    const int Maxn = 1e5 + 6;
    struct Node {
    	int l;
    	int r;
    	ll val;
    
    }T[Maxn * 40];
    
    int root[Maxn];
    ll arr[Maxn];
    
    vector<int>v;
    int n, m;
    int cnt = 0;
    
    int built(int &node, int l, int r) {
    	node = ++cnt;
    	T[node].val = 0;
    	if (l == r) return 0;
    	int mid = (l + r) / 2;
    	built(T[node].l, l, mid);
    	built(T[node].r, mid + 1, r);
    	
    }
    int update(int &node,int last,int be,int en,int i,ll val) {
    	T[++cnt] = T[last];	//复制一个单独的节点
    	node = cnt;//***接上节点,十分重要
    	if (be == en) {
    		T[node].val = val;
    		return T[node].val;
    	}
    	int mid = (be + en) / 2;
    	if (i <= mid) update(T[node].l, T[last].l, be, mid, i, val);
    	else update(T[node].r, T[last].r, mid + 1, en, i, val);
    	T[node].val = T[T[node].l].val + T[T[node].r].val;
    	return T[node].val;
    }
    
    ll query(int node,int be, int en, int LL, int RR) {//当前节点node  l--r,当前区间,,,x--y,所求区间
    	if (LL <= be && en <= RR) {
    		return T[node].val;
    	}
    	int mid = (be + en) / 2;
    	ll res = 0;
    	if(mid >= LL) res += query(T[node].l, be, mid, LL, RR);
    	if(RR > mid)  res+= query(T[node].r, mid + 1, en, LL, RR);
    	return res;
    }
    int t;
    
    
    map<ll, int>ins;
    int main() {
    	scanf("%d", &t);
    	while (t--) {
    		ins.clear();
    		cnt = 0;
    		scanf("%d", &n);
    		for (int i = 1; i <= n; i++) {
    			scanf("%lld", &arr[i]);
    		}
    		built(root[0], 1, n);
    		for (int i = 1; i <= n; i++) {
    			//没出现就直接加上
    			if (ins[arr[i]] == 0) {
    				update(root[i], root[i - 1], 1, n, i, arr[i]);
    				ins[arr[i]] = i;
    			}
    			else {
    				int tmp = 0;//tmp只是一个中介,就像交换数时候的 t 一样
    				update(tmp, root[i - 1], 1, n, ins[arr[i]], 0);
    				update(root[i], tmp, 1, n, i, arr[i]);
    				ins[arr[i]] = i;
    			}
    		}
    		scanf("%d", &m);
    
    		for (int i = 0; i < m; i++) {
    			int x, y;
    			scanf("%d%d", &x, &y);
    			ll ans = query(root[y], 1, n, x, y);
    			printf("%lld
    ",ans);
    
    		}
    	}
    	return 0;
    }
    

      

    https://blog.csdn.net/why932346109/article/details/98955619

    这个大佬写的十分详细,我留下了以后准备着复习看吧

    画图之后就理解了,太强了!!!

    题意:给你一个长度为n的序列,m个询问:询问区间[L,R]中不同的数的和是多少?

    大概就是这样,最后附上新垣结衣

    寻找真正的热爱
  • 相关阅读:
    phpmyadmin和网页上面的乱码问题
    整理: Android HAL
    warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]-给char* 形参 传入 宏定义字符串
    ubuntu 输入法莫名其妙变繁体
    linux内核版本号添加字符/为何有时会自动添加“+”号以及怎么去掉
    Unable to handle kernel NULL pointer dereference at virtual address 00000000
    Ubuntu 18.04 安装 Samba 服务器及配置
    linux查看版本信息
    图解:电压掉电监测电路如何实现检测工作?
    精密全波整流+一阶RC滤波器检测市电电压
  • 原文地址:https://www.cnblogs.com/lesning/p/11385069.html
Copyright © 2011-2022 走看看