蓝桥 log大侠

标题:Log大侠

atm参加了速算训练班,经过刻苦修炼,对以2为底的对数算得飞快,人称Log大侠。

一天,Log大侠的好友 drd 有一些整数序列需要变换,Log大侠正好施展法力...

变换的规则是: 对其某个子序列的每个整数变为: [log_2 (x) + 1] 其中 [] 表示向下取整,就是对每个数字求以2为底的对数,然后取下整。
例如对序列 3 4 2 操作一次后,这个序列会变成 2 3 2。

drd需要知道,每次这样操作后,序列的和是多少。

【输入格式】
第一行两个正整数 n m 。
第二行 n 个数,表示整数序列,都是正数。
接下来 m 行,每行两个数 L R 表示 atm 这次操作的是区间 [L, R],数列序号从1开始。

【输出格式】
输出 m 行,依次表示 atm 每做完一个操作后,整个序列的和。

  这题暴力肯定可以得一部分的,区间大小最差的情况就是每次都给L=1,R=N,这时暴力肯定不行的,会写线段树的话,可以看出这题也就是单点更新以及总区间查询。而它没说数据范围,但就算是1e18的话,取log对于每个位置的数来说,它最多也就更新个60次左右,所以我们可以加个标记,代表这个区间内还有没有位置需要更新,然后再线段树维护,时间复杂度就是60*nlog(n)这样。

 1 #include<cstdio>
 2 #include<cmath>
 3 #define L(x) (x<<1)
 4 #define R(x) (x<<1|1)
 5 #define M(x) ((T[x].l+T[x].r)>>1)
 6 typedef long long ll;
 7 const int N=100118;
 8 struct Tree{
 9     bool flag;
10     int l,r;
11     ll sum;
12 }T[N<<2];
13 ll a[N];
14 void built(int id,int l,int r)
15 {
16     T[id].l=l;
17     T[id].r=r;
18     T[id].sum=0;
19     T[id].flag=false;
20     if(l==r)
21     {
22         T[id].sum=a[l];
23         T[id].flag=(a[l]>2ll);
24         return ;
25     }
26     built(L(id),l,M(id));
27     built(R(id),M(id)+1,r);
28     T[id].flag=T[L(id)].flag|T[R(id)].flag;
29     T[id].sum=T[L(id)].sum+T[R(id)].sum;
30 }
31 void modify(int id,int l,int r)
32 {
33     if(!T[id].flag)
34         return ;
35     if(T[id].l==T[id].r)
36     {
37         T[id].sum=(ll)floor(log2(1.0*T[id].sum)+1.0);
38         T[id].flag=(T[id].sum>2ll);
39         return ;
40     }
41     if(l<=M(id))
42         modify(L(id),l,r);
43     if(r>M(id))
44         modify(R(id),l,r);
45     T[id].flag=T[L(id)].flag|T[R(id)].flag;
46     T[id].sum=T[L(id)].sum+T[R(id)].sum;
47 }
48 int main()
49 {
50     int n,m,l,r;
51     scanf("%d%d",&n,&m);
52     for(int i=1;i<=n;i++)
53         scanf("%lld",&a[i]);
54     built(1,1,n);
55     while(m--)
56     {
57         scanf("%d%d",&l,&r);
58         modify(1,l,r);
59         printf("%lld\n",T[1].sum);
60     }
61     return 0;
62 }

线段树下线段果

  不懂线段树的话,知道stl的map的话,还有种map的写法,思路一样,当某个位置的值<=2时就把它从map删去。

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<map>
 4 using namespace std;
 5 typedef long long ll;
 6 map<int,ll> mmp;
 7 map<int,ll>::iterator b,e,temp;
 8 int main()
 9 {
10     int n,m,l,r;
11     ll sum=0;
12     scanf("%d%d",&n,&m);
13     for(int i=1;i<=n;i++)
14     {
15         scanf("%lld",&mmp[i]);
16         sum+=mmp[i];
17     }
18     while(m--)
19     {
20         scanf("%d%d",&l,&r);
21         b=mmp.lower_bound(l);
22         e=mmp.upper_bound(r);
23         while(b!=e)
24         {
25             temp=b;
26             b++;
27             sum-=temp->second;
28             temp->second=(ll)floor(1.0*log2(temp->second)+1.0);
29             sum+=temp->second;
30             if(temp->second<=2)
31                 mmp.erase(temp);
32         }
33         printf("%lld\n",sum);
34     }
35     return 0;
36 }

STLwd

原文地址:https://www.cnblogs.com/LMCC1108/p/10907731.html

时间: 2024-10-12 17:44:08

蓝桥 log大侠的相关文章

蓝桥杯Log大侠(线段树单点区间更新)

标题:Log大侠 atm参加了速算训练班,经过刻苦修炼,对以2为底的对数算得飞快,人称Log大侠. 一天,Log大侠的好友 drd 有一些整数序列需要变换,Log大侠正好施展法力... 变换的规则是: 对其某个子序列的每个整数变为: [log_2 (x) + 1]  其中 [] 表示向下取整,就是对每个数字求以2为底的对数,然后取下整.     例如对序列 3 4 2 操作一次后,这个序列会变成 2 3 2.         drd需要知道,每次这样操作后,序列的和是多少. [输入格式] 第一行

C语言 &#183; LOG大侠

标题:LOG大侠 atm参加了速算训练班,经过刻苦修炼,对以2为底的对数算得飞快,人称Log大侠. 一天,Log大侠的好友 drd 有一些整数序列需要变换,Log大侠正好施展法力... 变换的规则是: 对其某个子序列的每个整数变为: [log_2 (x) + 1] 其中 [] 表示向下取整,就是对每个数字求以2为底的对数,然后取下整. 例如对序列 3 4 2 操作一次后,这个序列会变成 2 3 2. drd需要知道,每次这样操作后,序列的和是多少. [输入格式]第一行两个正整数 n m .第二行

蓝桥杯第五届决赛B组

1.标题:年龄巧合 小明和他的表弟一起去看电影,有人问他们的年龄.小明说:今年是我们的幸运年啊.我出生年份的四位数字加起来刚好是我的年龄.表弟的也是如此.已知今年是2014年,并且,小明说的年龄指的是周岁. 请推断并填写出小明的出生年份. 这是一个4位整数,请通过浏览器提交答案,不要填写任何多余的内容(比如,他表弟的出生年份,或是他们的年龄等等) #include <iostream> #include <algorithm> #include <stdio.h> us

几道STL题目(FJUT - OJ STL训练1)

这个OJ一直在做,一些专题题目都很好,从易至难,阶梯上升,很适合像我这样的蒟蒻 =7= 这篇是关于其中一个专题训练的题解思路及代码   http://120.78.128.11/Contest.jsp?cid=486 所有题面我就不贴了,各位自行去看,链接在上一行 =7= 一.求众数(Map标记+Set) 其实数组维护也可以做,但既然是STL训练,就用STL的东西了 用map标记数据和出现的次数,然后转入结构体存入map中 为什么不直接用set<map<T,T> >的形式 是因为m

第五届蓝桥杯软件大赛C/C++本科B组决赛解题报告

mnesia在频繁操作数据的过程可能会报错:** WARNING ** Mnesia is overloaded: {dump_log, write_threshold},可以看出,mnesia应该是过载了.这个警告在mnesia dump操作会发生这个问题,表类型为disc_only_copies .disc_copies都可能会发生. 如何重现这个问题,例子的场景是多个进程同时在不断地mnesia:dirty_write/2 mnesia过载分析 1.抛出警告是在mnesia 增加dump

算法-蓝桥杯习题(四)

蓝桥杯习题 蓝桥杯练习系统习题加答案,总共分为6部分,90%习题使用C语言解答,部分使用C++或者Java.大部分习题为搜索参考或者别人提供所得,不足之处在所难免,恳请批评指正(预计200多题,习题仅供学习交流) 目录 算法训练(详见 算法-蓝桥杯习题(一))Go 算法训练(详见 算法-蓝桥杯习题(二))Go 算法提高(waiting...) 历届试题(详见 算法-蓝桥杯习题(六))Go 历届试题(详见 算法-蓝桥杯习题(七))Go 蓝桥杯练习系统评测数据 链接: http://pan.baid

如何快速比较查询结果是否一致_转叶大侠

如何快速比较查询结果是否一致 如何快速比较查询结果是否一致 ([email protected]) [tom]> pager md5sum - PAGER set to 'md5sum -' ([email protected]) [tom]> select * from users; 6004a48a825ef527b3f090290ba9f0c0 - 1 row in set (0.00 sec) ([email protected]) [tom]> select * from us

【转】console.log 用法

转自http://www.cnblogs.com/ctriphire/p/4116207.html 大家都有用过各种类型的浏览器,每种浏览器都有自己的特色,本人拙见,在我用过的浏览器当中,我是最喜欢Chrome的,因为它对于调试脚本及前端设计调试都有它比其它浏览器有过之而无不及的地方.可能大家对console.log会有一定的了解,心里难免会想调试的时候用alert不就行了,干嘛还要用console.log这么一长串的字符串来替代alert输出信息呢,下面我就介绍一些调试的入门技巧,让你爱上co

2015年蓝桥杯省赛B组C/C++(试题+答案)

首先说,这次我是第二次参加蓝桥杯(大学里最后一次),可这次去连个三等都没拿到,有些心灰意冷,比上一次还差, 当时看到成绩出来的时候有些失落,但是跌倒了,再站起来继续跑就可以了.可能是状态不好吧,纯属自我安慰. 接下来我把今年的题目又重新做了一遍,写下了这篇博客,如果也有需要探讨答案的,希望可以有帮助. 第一题: 第1题:统计不含4的数字 题目大意 统计10000至99999中,不包含4的数值个数. 解题分析: 第一种解法: 数学方法,这种是在网上看到的一种解法: 最高位除了0.4不能使用,其余8