CodeForces 339D Xenia and Bit Operations(线段树点修改)
2015-08-23 20:30
579 查看
题目链接:
http://codeforces.com/problemset/problem/339/D
解题思路:
题目大意:
输入n和m分别表示有2^n个数和m个更新,每次更新只把p位置的值改成b,然后输出整个序列运算后的值,但是这个运算比较麻烦, 最下面一层数字两两之间进行或运算得到原来数目一半的数字,然后剩下的再两两之间进行异或运算,再得到一半,然后再或,再异或。。。。。。直到得到一个数字为止,这个数字就是每次询问的结果。
算法思想:
如果只有一种运算,就是简单的线段树点更新,区间查询问题。然而现在,我们要确定什么时候用or 什么时候用xor, 不过想想看,最下面一层是用or, 总共有n层,因为or和xor是交替进行的,所以我们就可以用n确定每层的运算,然后在建树和更新的时候分情况讨论就可以了。
AC代码:
http://codeforces.com/problemset/problem/339/D
解题思路:
题目大意:
输入n和m分别表示有2^n个数和m个更新,每次更新只把p位置的值改成b,然后输出整个序列运算后的值,但是这个运算比较麻烦, 最下面一层数字两两之间进行或运算得到原来数目一半的数字,然后剩下的再两两之间进行异或运算,再得到一半,然后再或,再异或。。。。。。直到得到一个数字为止,这个数字就是每次询问的结果。
算法思想:
如果只有一种运算,就是简单的线段树点更新,区间查询问题。然而现在,我们要确定什么时候用or 什么时候用xor, 不过想想看,最下面一层是用or, 总共有n层,因为or和xor是交替进行的,所以我们就可以用n确定每层的运算,然后在建树和更新的时候分情况讨论就可以了。
AC代码:
#include <iostream> #include <cstdio> using namespace std; const int maxn = 1<<17+5; struct node{ int l,r; int sum; }tree[maxn<<2]; int a[maxn]; void build(int id,int l,int r,int op){ tree[id].l = l; tree[id].r = r; if(l == r){ tree[id].sum = a[l]; return; } int mid = (l+r)>>1; build(id<<1,l,mid,-op); build(id<<1|1,mid+1,r,-op); if(op == 1) tree[id].sum = tree[id<<1].sum^tree[id<<1|1].sum; else tree[id].sum = tree[id<<1].sum|tree[id<<1|1].sum; } void update(int id,int x,int val,int op){ if(tree[id].l == x && tree[id].r == x){ tree[id].sum = val; return; } int mid = (tree[id].l+tree[id].r)>>1; if(x <= mid) update(id<<1,x,val,-op); else update(id<<1|1,x,val,-op); if(op == 1) tree[id].sum = tree[id<<1].sum^tree[id<<1|1].sum; else tree[id].sum = tree[id<<1].sum|tree[id<<1|1].sum; } int query(int id,int l,int r){ if(tree[id].l == l && tree[id].r == r){ return tree[id].sum; } int mid = (tree[id].l+tree[id].r)>>1; if(r <= mid) return query(id<<1,l,r); if(l > mid) return query(id<<1|1,l,r); return query(id<<1,l,mid)^query(id<<1|1,mid+1,r); } int main(){ int n,m; while(~scanf("%d%d",&n,&m)){ int num = 1<<n,op; for(int i = 1; i <= num; i++) scanf("%d",&a[i]); if(n&1) op = -1;//或 else op = 1;//异或 build(1,1,num,op); int a,b; while(m--){ scanf("%d%d",&a,&b); update(1,a,b,op); printf("%d\n",query(1,1,num)); } } return 0; }
相关文章推荐
- linux系统查找磁盘中的大文件命令
- Linux 安装ibus极点五笔输入法备忘录
- Linux 安装ibus极点五笔输入法备忘录
- django中for 标签的 forloop
- ### Hadoop
- Centos7安装cobbler2.6.9自动化部署工具
- Nginx反向代理配置
- 【POJ 3258】 River Hopscotch (二分)
- 我的架构师梦想日记
- bash 变量
- bash 基本功能
- shell编程基础
- shell基础
- linux 截图利器-scrot
- SHOPPING MALL OPENCART 自适应主题模板 ABC-0157
- linux 文件系统管理.txt
- SHOPPING MALL OPENCART 自适应主题模板 ABC-0157
- linux 系统管理.txt
- 创建虚拟机生成虚拟机全程日志打印输出流程详解(openstack开发必备)
- linux常用命令