HDU4902(线段树)练习题
来源:互联网 发布:sop16 单片机 编辑:程序博客网 时间:2024/05/18 03:58
如果你还是迷迷糊糊的话,建议先休息一下,前方高能!!!
题目链接:点这里
大概意思就是。
给出一个数列,m次操作,序列长度和操作次数都不超过100000。
输入:k l r x
k表示操作类别
操作分两种:
(1)把[l,r]区间的数字都变成x。
(2)把[l,r]区间中比x大的数字变成和x的最大公约数。
输出:
操作后的数组
如果你没学过线段树,你可能会用普通的解法,结果是超时(我试过),那么用线段树如何解呢?
先发着,以后再写吧,不早了。zzz
/*hdu4902线段树,书上版本妙妙妙呀*/#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define mid (r+l>>1)#define lc (d<<1)#define rc (d<<1|1)const int mmax = 100002;struct tree{ int lzx;//lazy懒x表示可替代x //感觉可以用bool来替代 int v; //结点值,可替代x}tr[mmax << 2];struct queue{ int k, l, r, x;}que[mmax];int val[mmax];int gcd(int a, int b){ return b == 0 ? a : gcd(b, a%b);}void push(int d)//维护最大的,为了后面优化{ tr[d].v = max(tr[lc].v, tr[rc].v);}void build(int d, int l, int r){ if (l == r) { tr[d].v = val[l]; tr[d].lzx = -1; return; } tr[d].lzx = -1;//放上面和build下面一样 build(lc, l, mid); build(rc, mid + 1, r); push(d);}void lazy(int d)//懒操作de延伸{ if (tr[d].lzx != -1) { tr[lc].lzx = tr[rc].lzx = tr[d].lzx; tr[lc].v = tr[rc].v = tr[d].v; tr[d].lzx = -1;//生效完还原 }}void f1(int d, int l, int r, int left, int right, int x){ if (l == left && r == right) { tr[d].lzx = x; tr[d].v = x; return; } lazy(d); if (left > mid) f1(rc, mid + 1, r, left, right, x);//区间在右边 else if (right <= mid) f1(lc, l, mid, left, right, x); //等于只能右边加 else { f1(rc, mid + 1, r, mid + 1, right, x);//这里要变一下 f1(lc, l, mid, left, mid, x); } push(d);}void f2(int d, int l, int r, int left, int right, int x){ if (l == left && r == right) { if (tr[d].v <= x) return; if (tr[d].lzx != -1) { tr[d].v = gcd(tr[d].v, x); tr[d].lzx = tr[d].v; if (l == r) val[l] = tr[d].lzx;//感觉多余 return; } if (l == r)//和模板很像 { if (val[l] > x) val[l] = gcd(val[l], x); return; } lazy(d); f2(lc, l, mid, left, mid, x); f2(rc, mid + 1, r, mid + 1, right, x); push(d); return; } lazy(d); if (left > mid) f2(rc, mid + 1, r, left, right, x);//区间在右边 else if (right <= mid) f2(lc, l, mid, left, right, x); //等于可以加 else { f2(rc, mid + 1, r, mid + 1, right, x); f2(lc, l, mid, left, mid, x); } push(d);}void out(int d, int l, int r){ if (tr[d].lzx != -1) { for (int i = l; i <= r; i++) { printf("%d ", tr[d].lzx);//一样的是d } return; } if (l == r) { printf("%d ", val[l]); return; } lazy(d); out(lc, l, mid); out(rc, mid + 1, r);}int main(){ int t; scanf("%d", &t); while (t--) { //初始化 memset(val, 0, sizeof(val)); //输入 int n1; scanf("%d", &n1); for (int i = 1; i <= n1; i++) { scanf("%d", &val[i]); } build(1, 1, n1); int n2; scanf("%d", &n2); for (int i = 1; i <= n2; i++) { scanf("%d%d%d%d", &que[i].k, &que[i].l, &que[i].r, &que[i].x); } //处理 for (int i = 1; i <= n2; i++) { if (que[i].k == 1) { f1(1, 1, n1, que[i].l, que[i].r, que[i].x); } else { f2(1, 1, n1, que[i].l, que[i].r, que[i].x); } /* out(1, 1, n1); printf("\n");*/ } out(1, 1, n1); printf("\n"); } return 0;}
下面是我的代码
/*hdu4902线段树,自己打的妙妙妙呀*/#include<iostream>#include<cstdio>#include<algorithm>using namespace std;#define lc (d<<1)#define rc (d<<1|1)#define mid (l+r>>1)const int mmax = 100005;int val[mmax];struct tree{ int v; bool lz;//懒操作标记,lazy简写}tr[mmax << 2];int gcd(int a, int b){ return b == 0 ? a : gcd(b, a%b);}//懒操作void lazy(int d){ if (tr[d].lz) { tr[lc].v = tr[rc].v = tr[d].v; tr[lc].lz = tr[rc].lz = true; tr[d].lz = false; }}void push(int d){ tr[d].v = max(tr[lc].v, tr[rc].v);}void build(int d, int l, int r){ if (l == r) { tr[d].v = val[l]; tr[d].lz = false; return; } tr[d].lz = false; build(lc, l, mid); build(rc, mid + 1, r); push(d);}void f1(int d, int l, int r, int left, int right, int x){ if (l == left && r == right) { tr[d].lz = true; tr[d].v = x; return; } lazy(d); if (left > mid) f1(rc, mid+1, r, left, right, x); else if (right <= mid) f1(lc, l, mid, left, right, x); else { f1(rc, mid+1, r, mid+1, right, x); f1(lc, l, mid, left, mid, x); } push(d);}void f2(int d, int l, int r, int left, int right, int x){ if (l == left && r == right) { if (tr[d].v <= x) return; //lazy说明子结点的tr[d].v是一样的,于是处理父结点就可以了 if (tr[d].lz) { tr[d].v = gcd(tr[d].v, x); return; } if (l == r)//没有优化的话,只能一个一个点来处理 { tr[d].v = gcd(tr[d].v, x); return; } lazy(d); f2(rc, mid+1, r, mid+1, right, x); f2(lc, l, mid, left, mid, x); push(d); return; } lazy(d); if (left > mid) f2(rc, mid+1, r, left, right, x); else if (right <= mid) f2(lc, l, mid, left, right, x); else { f2(rc, mid+1, r, mid+1, right, x); f2(lc, l, mid, left, mid, x); } push(d);}void out(int d, int l, int r){ if (tr[d].lz) { for (int i = l; i <= r; i++) { printf("%d ", tr[d].v); } return; } if (l == r) { printf("%d ", tr[d].v); return; } // lazy(d); out(lc, l, mid); out(rc, mid + 1, r);}int main(){ int t; scanf("%d", &t); while (t--) { int n1; scanf("%d", &n1); for (int i = 1; i <= n1; i++) { scanf("%d", &val[i]); } build(1, 1, n1); int n2; scanf("%d", &n2); for (int i = 1; i <= n2; i++) { int k, l, r, x; scanf("%d%d%d%d", &k, &l, &r, &x); if (k == 1) { f1(1, 1, n1, l, r, x); } else { f2(1, 1, n1, l, r, x); } } out(1, 1, n1); printf("\n"); } return 0;}
阅读全文
0 0
- HDU4902(线段树)练习题
- HDU4902-Nice boat(线段树)
- hdu4902 线段树
- HDU4902 线段树
- 线段树lazy标记??Hdu4902
- hdu4902 线段树区间更新
- 线段树特殊懒惰标记hdu3954(hdu4902)
- HDU4902:Nice boat(线段树lazy)
- HDU4902 Nice Boat(14多校联合4-1006)线段树区间更新
- 入门题 _14多校—线段树 HDU4902 Nice boat
- HDU4902巧妙分析避开线段树的使用
- HDU1698(线段树)练习题
- hdu4902
- 线段树练习题一
- 线段树练习题一
- 线段树练习题二
- 线段树练习题三
- 线段树练习题三
- 相机采集高速运行物体,曝光时间设定以解决图像拖影现象
- 再谈CVE-2017-7047 Triple_Fetch和iOS 10.3.2沙盒逃逸
- Codeforces 35E Parade(扫描线 线段树||STL)
- 判别式模型与生成式模型的区别
- 选择排序
- HDU4902(线段树)练习题
- 二叉树问题---统计完全二叉树的节点个数
- JAVA类加载器学习
- Java之Annotation
- Java wait(),yield(),sleep()的区别
- 利用tensorflow进行单词分类
- leetcode[Perfect Number]
- VBA处理文件框架代码 【第一部分:处理流程】
- 架构师必看书籍