【题】【线段树(不用lazy的区间修改)】NKOJ 2997 狗 【nodgd造水题】

来源:互联网 发布:iphone延时摄影软件 编辑:程序博客网 时间:2024/05/19 13:57

NKOJ 2997 狗 【nodgd造水题】
时间限制 : 6000 MS 空间限制 : 131072 KB

问题描述
nodgd家里有很多狗!太多的狗给nodgd带来了各种麻烦,于是nodgd决定开个赶走一些狗!
nodgd首先按照狗的品种把所有狗分成N类,依次是第1类,第2类,…,第N类。刚开始第i类有ai只。
nodgd有时候会心情不爽,就会把第l类、第l+1类、第l+2类、…、第r-1类、第r类的每类狗都进行这样的操作:
第一步,把这类狗排成一个尽量大的正方形方阵,多余的狗就赶走!
第二步,在正方形方阵中每一横排任选一条狗留下,其余全部赶走!
当然,狗也是需要喂食的,喂食之前需要先知道有多少条狗。因为赶走了一些狗,所以nodgd也记不清楚到底有多少条狗了,他可能会问你,第l类、第l+1类、第l+2类、…、第r-1类、第r类一共还剩多少条狗?你作为一个优秀的程序员,当然可以写个程序来回答nodgd的提问啦!
简化版题目描述:给个序列,区间开方,向下取整,区间求和。

输入格式
第一行两个整数N,M,分别表示狗的种类数和操作次数
第二行N个整数a1,a2,…,aN,表示每类狗一开始有多少条
接下来M行,每行三个整数k,l,r。若k=0则表示nodgd心情不爽了又要赶走一些狗了,若k=1则表示nodgd打算给狗喂食了就先向你提问

输出格式
对于nodgd的每次提问输出答案

样例输入
10
1 2 3 4 5 6 7 8 9 10
5
0 1 10
1 1 10
1 1 5
0 5 8
1 4 8

样例输出
19
7
6

提示
样例解释:
第一次操作之后狗的数量分别是1,1,1,2,2,2,2,2,3,3.
第四次操作之后狗的数量分别是1,1,1,2,1,1,1,1,3,3.
数据范围:
1<=N<=100000
1<=M<=100000
1<=ai<=1012
1<=l<=r<=N

来源 感谢nodgd抄袭别人的题目并提供数据

思路:
每次修改虽然是区间,但是每次一定要修改到叶节点,所以用不用lazy都差不多…..
结论:lazy使用条件:不知道子树信息也可以更新
注意开方很容易开成1,用1来“剪枝”。

#include<cstdio>#include<iostream>#include<cmath>using namespace std;#define ll long longconst int need=100003;struct fy{ll val;int a,b;}t[need<<1];int le[need<<1],ri[need<<1],tot=0;ll a[need];ll x,y;inline void in_(ll &d){    bool mark=false;char t=getchar();    while(t<'0'||t>'9'){if(t=='-') mark=true;t=getchar();}    for(d=0;t>='0'&&t<='9';t=getchar())d=(d<<3)+(d<<1)-'0'+t;    if(mark)d=-d;}  char o[100];inline void out_(ll x){       int l=1;    if(x<0) x=-x,putchar('-');      if(!x) putchar('0');      for(;x;x/=10) o[l++]=x%10+'0';      for(l--;l;l--)putchar(o[l]);      putchar('\n');  }  void build(int x,int y){    int s=++tot;    t[s].a=x,t[s].b=y;    if(x==y)    {        t[s].val=a[x];        return ;    }    le[s]=tot+1;build(x,(x+y)>>1);    ri[s]=tot+1;build((x+y)/2+1,y);    t[s].val=t[le[s]].val+t[ri[s]].val;} void modify(int s){    if(t[s].val==t[s].b-t[s].a+1) return ;//表示该区间所有狗都为1,修改后无变化。    if(t[s].a>y||t[s].b<x) return ;    if(t[s].a==t[s].b)     {        t[s].val=t[s].val==1?1:floor(sqrt(t[s].val));        return ;    }    modify(le[s]),modify(ri[s]);     t[s].val=t[le[s]].val+t[ri[s]].val;}ll getans(int s){    if(t[s].a>y||t[s].b<x) return 0;    if(x<=t[s].a&&t[s].b<=y) return t[s].val;    return getans(le[s])+getans(ri[s]);}int main(){    int n;scanf("%d",&n);    for(int i=1;i<=n;i++)     in_(a[i]);//scanf("%I64d",a[i]);    build(1,n);    int m;scanf("%d",&m);    ll aa;    for(int i=1;i<=m;i++)    {        in_(aa),in_(x),in_(y);//scanf("%d%d%d",&a,&x,&y);        if(aa==0) modify(1);        else out_(getans(1));//printf("%I64d",getans(1));    }}
0 0
原创粉丝点击