标签:数组 例子 大数 center 一段 page 最大 ati 线段树
输入
产量
示例输入
2 8 10
示例输出
1 15 9 11
题意:求以当前为根节点下的最小值节点与最大值节点
思路:乍一看不知道是啥,但是仔细看最小节点最大节点与根节点又有些关系,最小值节点=根节点-x 最大值节点=根节点+x
但是每个对应的x值又不同,说明也与根节点的值有关系
我们就拿几个例子进行比较
我们只需要把用最小值把x求出来,最大值可以把x代进去求出
6 5 化成二进制 110 101
12 9 化成二进制 1100 1001
8 1 化成二进制 1000 0001
我们可以发现每个都是把二进制最低的1去掉再加1,然后我们求二进制最低的1有个特殊的办法 树状数组的lowbit 前不久刚学的23333
所以x=lowbit-1
那么最小值节点=x-lowbit(x)+1 最大值节点=x+lowbit(x)-1
然后这题就简单了
#include<cstdio> #include<cstring> using namespace std; int lowbit(int x) { return x&(-x); } int main() { int n,x; scanf("%d",&n); while(n--) { scanf("%d",&x); printf("%d %d\n",x-lowbit(x)+1,x+lowbit(x)-1); } }
初学者程序员Xenia有一个序列a,由2 n个非负整数组成:a 1,? a 2,...,? a 2 n。Xenia目前正在研究位操作。为了更好地了解他们的工作,森雅决定计算一些数值v的一个。
即,计算值v需要几次迭代。在第一次迭代中,捷尼亚写入一个新的序列一个1 或 一个2,? 一个3 或 一个4,...,? 一个2 ? ?- 1 或 一个2 ?,由2个? ?- 1元件。换句话说,她写下序列a的相邻元素的按位或。在第二次迭代中,Xenia写入了按位独占在第一次迭代之后获得的序列的相邻元素的OR。在第三次迭代中,Xenia写入在第二次迭代之后获得的序列的相邻元素的按位或。等等; 按位异或运算和按位异或运算。最后,她得到一个由一个元素组成的序列,该元素是v。
我们来看一个例子。假设序列a ?=(1,2,3,4)。然后让我们写下所有变换(1,2,3,4) ?→?(1 或 2 = 3,3 或 4 = 7) ?→? (3 xor 7 = 4)。结果是v ?= 4。
给你Xenia的初始序列。但是要计算给定序列的值v太容易了,所以给你额外的m个查询。每个查询都是一对整数p,? b。查询p,? b意味着您需要执行赋值a p ?=? b。每次查询后,您需要为新序列a打印新值v。
第一行包含两个整数?和米 (1≤? ? ?≤17,1≤? 米 ?≤10 5)。下一行包含2个?整数一个1,? 一个2,...,? 一个2 ?(0≤? 一个我 ?<2 30)。每个下一个的米线包含查询。在我个行包含整数p 我,? b 我 (1个≤? p 我 ?≤2 ?,0≤? b我 ?<2 30)- 第 i个查询。
打印m个整数 - 第i个整数表示第i个查询后的序列a的值v。
2 4
1 6 3 5
1 4
3 4
1 2
1 2
1
3
3
3
题意:输入总共2^n个数,然后让相邻的两个数进行|操作或者^操作,当是第一次的时候是|,第二次是^,这样交替进行
然后m次修改操作,这明显就是线段树的模板题,但是多了一个| ^ 的交替运算,可以判断这棵树的层数来判断是什么操作,然后发现n就是树的层数
或者用全局变量递归到最底层的时候实时更新也行
#include<cstdio> #include<cstring> #include<cmath> using namespace std; struct sss { int left; int right; int value; }mp[ ((1 << 17) + 5)<<2]; int n,m; int a[ (1 << 17) + 5]; void build(int cnt,int left,int right,int op) { mp[cnt].left=left; mp[cnt].right=right; if(left==right) { mp[cnt].value=a[left]; return ; } int mid=(left+right)/2; build(cnt<<1,left,mid,-op); build(cnt<<1|1,mid+1,right,-op); if(op==1) mp[cnt].value=mp[cnt<<1].value|mp[cnt<<1|1].value; else mp[cnt].value=mp[cnt<<1].value^mp[cnt<<1|1].value; } void updata(int cnt,int left,int right,int num,int value,int op) { if(left==right) { mp[cnt].value=value; return; } int mid=(left+right)/2; if(num<=mid) updata(cnt<<1,left,mid,num,value,-op); else updata(cnt<<1|1,mid+1,right,num,value,-op); if(op==1) mp[cnt].value=mp[cnt<<1].value|mp[cnt<<1|1].value; else mp[cnt].value=mp[cnt<<1].value^mp[cnt<<1|1].value; } int main() { scanf("%d%d",&n,&m); int t=(int)pow(2,n); for(int i=1;i<=t;i++) { scanf("%d",&a[i]); } int op; if(n&1) op=1; else op=-1; build(1,1,t,op); int x,y; for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); updata(1,1,t,x,y,op); printf("%d\n",mp[1].value); } }
标签:数组 例子 大数 center 一段 page 最大 ati 线段树
原文地址:https://www.cnblogs.com/Lis-/p/9151973.html