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 每做完一个操作后,整个序列的和。
例如,输入:
3 3
5 6 4
1 2
2 3
1 3
程序应该输出:
10
8
6
【数据范围】
对于 30% 的数据, n, m <= 10^3
对于 100% 的数据, n, m <= 10^5
资源约定:
峰值内存消耗 < 256M
一天,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 每做完一个操作后,整个序列的和。
例如,输入:
3 3
5 6 4
1 2
2 3
1 3
程序应该输出:
10
8
6
【数据范围】
对于 30% 的数据, n, m <= 10^3
对于 100% 的数据, n, m <= 10^5
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,m;
int num[100010];
int l,r;
while(cin >> n >> m){
for(int i = 1; i <= n; i++)
cin >> num[i];
for(int i = 0; i < m; i++){
cin >> l >> r;
int sum = 0;
for(int j = l; j <= r; j++){
num[j] = floor(log(num[j])/log(2)+1);
}
for(int j = 1; j <= n; j++)
sum += num[j];
cout << sum << endl;
}
}
return 0;
}
恩....应该不会这么简单的是吧,应该会超时的吧,我没测试过我也不知道,,,不过混点分还是可以的
这里对区间里的值进行对数运算,可以看做是更新,区间更新,求和,很明显是线段树....
不过下面代码中的优化部分没有想懂....
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int num[maxn];
int tree[maxn*2];
int n,m;
int l,r;
int cnt;
void build(int x,int l, int r)
{
if (l == r){
cin >> tree[x];
if (tree[x] == 1){//统计数值1的个数 ,方便优化程序
cnt++;
tree[x] = 2;//将所有1均变为2,防止1干扰程序优化
}
return;
}
int mid = (l+r)/2;
build(x*2,l,mid);
build(x*2+1,mid+1,r);
tree[x] = tree[x*2]+tree[x*2+1];
}
void update(int x,int l,int r,int L,int R)
{
if (tree[x] == (r-l+1)*2){ //如果全为2,直接返回
return ;
}
if (l == r){
tree[x] = num[tree[x]];
return;
}
int mid = (l+r)/2;
if (R <= mid)
update(x*2,l,mid,L,R);
else if (L > mid)
update(x*2+1,mid+1,r,L,R);
else{
update(x*2,l,mid,L,mid);
update(x*2+1,mid+1,r,mid+1,R);
}
tree[x] = tree[x*2]+tree[x*2+1];
}
int main()
{
for(int i = 1; i <= maxn; i++) //打表
num[i] = (int)(log2(i) + 1);
cin >> n >> m;
build(1,1,n);
while(m--){
cin >> l >> r;
update(1,1,n,l,r);
cout << tree[1]-cnt << endl;
}
return 0;
}