• 校门外的树2 contest 树状数组练习 T4


    Description

    校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:K=1,读入l,r表示在区间[l,r]中种上一种树,每次操作种的树的种类都不同。K=2,读入l,r表示在区间[l,r]之间能见到多少种树(l,r>0)。


    Input

    第一行n,m,表示道路总长为n,共有m个操作。接下来m行,为m个操作。


    Output

    对于每个k=2输出一个答案。


    Hint

    对于20%的数据保证,n,m<=100。
    对于60%的数据保证,n <=1000,m<=50000。
    对于100%的数据保证,n,m<=50000。


    Solution

    用两个区间的树状数组分别维护起点数量和终点数量。那么查询的时候ans就等于r前面的起点数量减去l-1前面的终点数量。因为l-1前面就已经终点了的话,这种树就不包含在查询的这个区间里面。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define maxn 50005
    #define lowbit(x) (x&(-x))
    #define int long long
    using namespace std;
    int c1[maxn],c2[maxn],c3[maxn],c4[maxn];
    int n,m,x,y,z;
    void doAdd(int x,int dd){
    	int f=x;
    	while(x<=n){
    		c1[x]+=f*dd;
    		c3[x]+=dd;
    		x+=lowbit(x);
    	}
    }
    void doadd(int x,int dd){
    	int f=x;
    	while(x<=n){
    		c2[x]+=f*dd;
    		c4[x]+=dd;
    		x+=lowbit(x);
    	}
    }
    int doFinD(int x){
    	int f=x,ans=0;
    	while(x>0){
    		ans+=(f+1)*c3[x]-c1[x];
    		x-=lowbit(x);
    	}
    	return ans;
    }
    int dofinD(int x){
    	int f=x,ans=0;
    	while(x>0){
    		ans+=(f+1)*c4[x]-c2[x];
    		x-=lowbit(x);
    	}
    	return ans;
    }
    signed main(){
    	scanf("%lld%lld",&n,&m);
    	for(int i=1;i<=m;i++){
    		scanf("%lld",&x);
    		if(x==1){
    			scanf("%lld%lld",&y,&z);
    			doAdd(y,1);
    			doAdd(y+1,-1);
    			doadd(z,1);
    			doadd(z+1,-1); 
    		}
    		else if(x==2){
    			scanf("%lld%lld",&y,&z);
    			printf("%lld
    ",doFinD(z)-dofinD(y-1));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    CPU 被客户机操作系统禁用. 重启或关闭虚拟机电源
    android怎么修改源码
    Git Gui for Windows的建库、克隆(clone)、上传(push)、下载(pull)、合并
    煮茶叶蛋口味鲜美的秘技
    屏蔽非法路由,好好上网!
    寂寞·韶华
    uml 的学习文章
    忧患人生的卓越指南——《周易》与人生哲理
    vblog 的 前景展望
    在数据库开发过程中,数据库、表、字段、视图、存储过程等的命名规则
  • 原文地址:https://www.cnblogs.com/virtual-north-Illya/p/10045445.html
Copyright © 2020-2023  润新知