zoukankan      html  css  js  c++  java
  • hdu 3874

    求一个序列中全部数字的和,当中数值同样的仅仅能计算一次。

    先储存全部的请求,然后依照它们的右边界排序,在查询的同一时候更新区间。这里事实上有一点点DP的味道,在它进行某个查询之前,保证全部的反复数字(除去最后一个)都被删除光了,而且有不能影响其它查询,所以呢,仅仅能从近期的那个操作进行计算。1次query就可以


    #include<iostream>
    #include<stdio.h>
    #include<string>
    #include<string.h>
    #include<algorithm>
    #include<vector>
    
    using namespace std;
    
    const int maxn = 50050;
    const int maxm = 200050;
    vector<int> vec;
    __int64 res[maxm];
    __int64 ans;
    int pre[1000050];
    
    void init()
    {
    	vec.clear();
    	vec.push_back(0);	
    	memset(pre, 0, sizeof(pre)); 
    }
    
    struct line{
    	int left, right, id;
    	bool operator<(const line &y)const
    	{
    		return right < y.right;
    	}
    }q[maxm];
    
    struct node{
    	int left, right;
    	__int64 sum;
    	int mid(){
    		return (left+right)/2;
    	}
    }tree[maxn*4];
    
    void buildTree(int left, int right, int rt)
    {
    	tree[rt].left = left;
    	tree[rt].right = right;
    	if(left == right){
    		int a;
    		scanf("%d", &a);
    		vec.push_back(a);
    		return ;
    	}
    	int mid = tree[rt].mid();
    	buildTree(left, mid, rt<<1);
    	buildTree(mid+1, right, rt<<1|1);
    	tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;	
    }
    
    void update(int left, int right, int rt, int pos, int add)
    {
    	if(left == right){
    		tree[rt].sum = add;
    		return ;
    	}
    	int mid = tree[rt].mid();
    	if(pos <= mid)
    		update(left, mid, rt<<1, pos, add);
    	if(pos > mid)
    		update(mid+1, right, rt<<1|1, pos, add);
    	tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;
    }
    
    void query(int left, int right, int rt, int L, int R)
    {
    	if(L <= left && R >= right){
    		ans += tree[rt].sum;
    		return ;
    	}
    	int mid = tree[rt].mid();
    	if(L <= mid)
    		query(left, mid, rt<<1, L, R);
    	if(R > mid)
    		query(mid+1, right, rt<<1|1, L, R);
    }
    
    int main()
    {
    	int T, M, N;
    	scanf("%d", &T);
    	while(T --)
    	{
    		scanf("%d", &N);
    		
    		init();
    		buildTree(1, N, 1);
    		
    		scanf("%d", &M);
    		for(int i = 1; i <= M; i ++)
    		{
    			scanf("%d%d", &q[i].left, &q[i].right);
    			q[i].id = i;
    		}
    		sort(q+1, q+M+1);//排序是从index=1開始的M个数 
    		
    		int qn = 0;
    		for(int i = 1; i <= N && qn <=M; i ++)
    		{
    			if(pre[vec[i]] != 0){
    				update(1, N, 1, pre[vec[i]], 0);
    			}
    			update(1, N, 1, i, vec[i]);
    			while(qn <= M && q[qn].right <= i){
    				ans = 0;
    				if(q[qn].right == i){
    					query(1, N, 1, q[qn].left, q[qn].right);
    					res[q[qn].id] = ans;
    				}
    				qn ++;
    			}
    			pre[vec[i]] = i; 
    		}
    		for(int i = 1; i <= M; i ++) printf("%I64d
    ", res[i]);
    	}
    	
    	return 0;
    } 


  • 相关阅读:
    C#中 @ 的用法
    ASP.NET页面间传值
    ASP.NET中常用的文件上传下载方法
    把图片转换为字符
    把图片转换为字符
    JavaScript 时间延迟
    Using WSDLs in UCM 11g like you did in 10g
    The Definitive Guide to Stellent Content Server Development
    解决RedHat AS5 RPM安装包依赖问题
    在64位Windows 7上安装Oracle UCM 10gR3
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4252087.html
Copyright © 2011-2022 走看看