zoukankan      html  css  js  c++  java
  • POJ 3468 A Simple Problem with Integers //线段树的成段更新

    A Simple Problem with Integers
    Time Limit: 5000MS   Memory Limit: 131072K
    Total Submissions: 59046   Accepted: 17974
    Case Time Limit: 2000MS

    Description

    You have N integers, A1A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

    Input

    The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
    The second line contains N numbers, the initial values of A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
    Each of the next Q lines represents an operation.
    "C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
    "Q a b" means querying the sum of AaAa+1, ... , Ab.

    Output

    You need to answer all Q commands in order. One answer in a line.

    Sample Input

    10 5
    1 2 3 4 5 6 7 8 9 10
    Q 4 4
    Q 1 10
    Q 2 4
    C 3 6 3
    Q 2 4
    

    Sample Output

    4
    55
    9
    15

    Hint

    The sums may exceed the range of 32-bit integers.

    Source

    /*
    	区间更新的lazy操作。
    */
    #include <stdio.h>
    
    struct node
    {
    	int l, r;
    	__int64 sum;
    	__int64 lazy;	//当成段更新时,往往不用更新到单个的点。lazy操作大大节省了时间。
    }tree[300005];
    int h[100005];
    __int64 sum;		//int超限
    
    void build(int l, int r, int n)
    {
    	int mid;
    	tree[n].l = l;
    	tree[n].r = r;
    	tree[n].lazy = 0;	//赋初值
    	if(l==r)
    	{
    		tree[n].sum = h[l];
    		return ;
    	}
    	mid = (l+r)/2;
    	build(l, mid, 2*n);
    	build(mid+1, r, 2*n+1);
    	
    	tree[n].sum = tree[2*n].sum+tree[2*n+1].sum;
    }
    void add(int l, int r, __int64 k, int n)
    {
    	int mid;
    	if(tree[n].l==l && tree[n].r==r)	//当须要更新的段 与 结点相应的段吻合时,直接把此结点的lazy值更新就可以,不须要再向下更新。
    	{
    		tree[n].lazy += k;
    		return;
    	}
    	
    	tree[n].sum += k*(r-l+1);		//当此区间包括须要更新的区间,但不吻合时,须要向下继续查找,此时须要更新这个父节点的sum值。
    	
    	mid = (tree[n].l + tree[n].r)/2;
    	if(r <= mid)
    		add(l, r, k, 2*n);
    	else if(l >=mid+1)
    		add(l, r, k, 2*n+1);
    	else
    	{
    		add(l, mid, k, 2*n);
    		add(mid+1, r, k, 2*n+1);
    	}
    }
    void qu(int l, int r, int n)
    {
    	int mid;
    	if(tree[n].l==l && tree[n].r==r)
    	{
    		sum += tree[n].sum + (r-l+1)*tree[n].lazy;	//当查找的段与 此结点的段吻合时,sum 值等于这个结点的sum加上lazy乘区间长度的值。
    		return ;
    	}
    	
    	if(tree[n].lazy!=0 && tree[n].l!=tree[n].r)	//当查找区间为此结点相应区间的子集时,须要将此结点相应的lazy值下放到其子节点,并把此结点的lazy值置为0。
    	{
    		add(tree[2*n].l, tree[2*n].r, tree[n].lazy, n);
    		add(tree[2*n+1].l, tree[2*n+1].r, tree[n].lazy, n);
    		tree[n].lazy = 0;
    	}
    	mid = (tree[n].l + tree[n].r)/2;
    
    	if(l >= mid+1)
    		qu(l, r, 2*n+1);
    	else if(r <= mid)
    		qu(l, r, 2*n);
    	else
    	{
    		qu(l, mid, 2*n);
    		qu(mid+1, r, 2*n+1);
    	}
    }
    
    int main()
    {
    	int n, q;
    	int i;
    	int a, b, c;
    	char ch[10];
    	
    	scanf("%d%d", &n, &q);
    	for(i=1; i<=n; i++)
    		scanf("%d", &h[i]);
    	
    	build(1, n, 1);
    	while(q--)
    	{
    		scanf("%s", ch);
    		if(ch[0]=='Q')
    		{
    			scanf("%d%d", &a, &b);
    			sum = 0;
    			qu(a, b, 1);
    			printf("%I64d
    ", sum);
    		}
    		else
    		{
    			scanf("%d%d%d", &a, &b, &c);
    			add(a, b, c, 1);
    		}
    	}
    	return 0;
    }


  • 相关阅读:
    centos下网络的基本配置方法讲解
    win8.1环境下硬盘安装centos6.5双系统
    新人出世
    Docker 仓库管理
    Docker Dockerfile
    Docker image创建之Hello world
    ASP.Net Core 发布到 Centos Docker
    C# 人工智能
    C#使用ML.Net完成人工智能预测
    无监督和有监督算法的区别
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4084918.html
Copyright © 2011-2022 走看看