hihoCoder #1078 : 线段树的区间修改

思路:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N=100010;
 4 int n, q, op, l, r, flag, sma;
 5 int w[N];
 6 int ans[N];
 7
 8 void cal(int t)//从t开始计算,ans[i]表示1~i的和
 9 {
10     for(int i=t; i<=n; i++)
11         ans[i]=ans[i-1]+w[i];
12 }
13
14 int main()
15 {
16     //freopen("input.txt", "r", stdin);
17     sma=0x7fffffff;
18     cin>>n;
19     for(int i=0; i<n; i++)    scanf("%d",&w[i+1]);
20     cin>>q;
21     cal(1);//先算一次
22     for(int i=0; i<q; i++)
23     {
24         scanf("%d",&op);
25         int a,b,c;
26         if(op)  //修改
27         {
28             scanf("%d%d%d",&a,&b,&c);
29             for(int i=a; i<=b; i++)    w[i]=c;
30             if(a<sma)
31                 sma=a;//需要修改的地方sma~n。若多次修改,只需要一次从最小的sma开始修改
32             flag=a;//需要修改的标志
33         }
34         else    //查询
35         {
36             if(flag)
37             {
38                 cal(sma);
39                 sma=0x7fffffff;
40                 flag=0;
41             }
42             scanf("%d%d", &a,&b);
43             printf("%d\n",ans[b]-ans[a-1]);
44         }
45     }
46     return 0;
47 }

偷懒的TLE代码

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int N=100010;
  4 int n, q, L, R, op, a, b, W;
  5 bool flag[N];
  6 struct node
  7 {
  8     int v;
  9     bool flag;
 10     node *ll,*rr;
 11
 12 };
 13
 14 node* create()  //创建节点
 15 {
 16     node *tmp=new(node);
 17     tmp->flag=tmp->v=0;
 18     tmp->ll=tmp->rr=0;
 19     return tmp;
 20 }
 21
 22 node* init_tree(int l,int r)    //初始化树
 23 {
 24     node *tmp=create();
 25     if(l==r)
 26     {
 27         scanf("%d",&tmp->v);
 28         return tmp;
 29     }
 30     tmp->ll=init_tree(l,(r+l)/2);
 31     tmp->rr=init_tree((r+l)/2+1,r);
 32     tmp->v =tmp->ll->v + tmp->rr->v;
 33     return tmp;
 34 }
 35
 36 int query(int l,int r,int LL,int RR,node *t)    //查询(欲查询的左,右,区间下限,上限,根)
 37 {
 38     if(l==LL&&r==RR)    return  t->v;
 39     int mid=((LL+RR)>>1);
 40     if(t->flag) //t的孩子要改
 41     {
 42         if(t->ll)
 43         {
 44             t->ll->flag=1;
 45             t->ll->v= t->v/(LL-RR+1)*(mid-LL+1);
 46         }
 47         if(t->rr)
 48         {
 49             t->rr->flag=1;
 50             t->rr->v= t->v/(LL-RR+1)*(RR-mid);
 51         }
 52         t->flag=0;
 53     }
 54
 55     if(l>mid)     return query(l, r, mid+1, RR, t->rr);
 56     if(r<=mid)    return query(l, r, LL, mid, t->ll);
 57     return query(l,mid,LL,mid,t->ll) + query(mid+1,r,mid+1,RR,t->rr);
 58 }
 59
 60 void update(int l,int r,int LL,int RR,node *t)   //修改。
 61 {
 62
 63     if(l==LL&&r==RR)
 64     {
 65         t->flag=1;
 66         t->v=(r-l+1)*W;
 67         return ;
 68     }
 69 //修改的过程中也可能遇到flag=1的情况,要进行改;
 70     int mid=((LL+RR)>>1);
 71     int tmp;
 72     if(l>mid)    update(l,r,mid+1,RR,t->rr);  //要改的在右边
 73     else if(r<=mid)    update(l,r,LL,mid,t->ll);
 74     else
 75     {
 76         update(l, mid, LL, mid, t->ll);
 77         update(mid+1, r, mid+1, RR, t->rr);
 78     }
 79     t->v=t->ll->v + t->rr->v;
 80 }
 81
 82
 83 int main()
 84 {
 85     freopen("input.txt", "r", stdin);
 86     cin>>n;
 87     node *tree=init_tree(1,n);
 88
 89     cin>>q;
 90     for(int i=0; i<q; i++)
 91     {
 92         scanf("%d",&op);
 93         if(op)  //修改
 94         {
 95             scanf("%d%d%d",&a,&b,&W);
 96             update(a,b,1,n,tree);
 97         }
 98         else    //查询
 99         {
100             scanf("%d%d",&L,&R);
101             printf("%d\n",query(L,R,1,n,tree) );
102         }
103     }
104     return 0;
105 }

还没完成代码

时间: 2024-08-05 14:06:24

hihoCoder #1078 : 线段树的区间修改的相关文章

hihoCoder #1078 : 线段树的区间修改(线段树区间更新板子题)

#1078 : 线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格——小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问——小Hi给出一段

hihoCode 1078 : 线段树的区间修改

#1078 : 线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格——小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问——小Hi给出一段

hihoCoder week20 线段树的区间修改

区间修改 区间查询 最后一场比赛前的无可救药的热身 #include <bits/stdc++.h> using namespace std; #define mid ((l+r)/2) #define ls (rt<<1) #define rs (rt<<1|1) const int N = 2e5+10; int n, s[N], tr[N], lz[N]; void build(int rt,int l,int r) { if(l ==r) { tr[rt] =

hiho一下20周 线段树的区间修改

线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格--小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问--小Hi给出一段区间[L, R]

线段树的区间修改

线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格--小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问--小Hi给出一段区间[L, R]

poj 3468:A Simple Problem with Integers(线段树,区间修改求和)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 58269   Accepted: 17753 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

模板 线段树的区间修改

线段树的区间修改 区间绝对标记 改成同一个数 注意打标记前 要先判断 是否有标记 这道题不能像加法标记一样 标记初始化为 0 如果这道题 可以将数变成 0 那么0 就不能为初始值了 然后我们初始值要选择一个不会被干扰到的数字 比如 -1 就不会变成 -1 另外还要注意在标记清空时 要将标记 变成 -1 而不是 0 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstr

POJ 2828 Buy Tickets (线段树,区间修改)

逆向思维.从最后一位开始考虑,用线段树查询空位置. #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <set> #include &l

培训补坑(day7:线段树的区间修改与运用)(day6是测试,测试题解以后补坑QAQ)

补坑咯~ 今天围绕的是一个神奇的数据结构:线段树.(感觉叫做区间树也挺科学的.) 线段树,顾名思义就是用来查找一段区间内的最大值,最小值,区间和等等元素. 那么这个线段树有什么优势呢? 比如我们要多次查询1-n中的最大值,那么我们如果使用暴力来查找,那么我们每次查找的复杂度就是O(n) 但是如果我们把一个个区间变成树上的一个个点,并且我们严格保证树的深度,那么我们每次查找的复杂度就是O(logn) 这样就能让查询变得更快. 我们先简单讲一下线段树的存储(图中的标号就是线段树数组标号) 这就是线段