hdu 4902 线段树双标记类型题
来源:互联网 发布:手机淘宝怎样朋友代付 编辑:程序博客网 时间:2024/05/29 14:16
比赛时没敲出来,似乎现在敲得还是不好
后来找了份题解,http://www.cnblogs.com/qq1012662902/p/3883614.html 600多msAC 很高效了
参考了之后写了代码 近期在重写一遍
</pre><pre name="code" class="cpp">#include <cstdio>#include <cstring>#include <algorithm>#include <string>#include <iostream>using namespace std;#define ls(rt) rt*2#define rs(rt) rt*2+1#define ll long long#define rep(i,s,e) for(int i=s;i<e;i++)#define repe(i,s,e) for(int i=s;i<=e;i++)#define IN(s) freopen(s,"r",stdin)const int MAXN = 100000+100;int gcd(int a, int b){ if(!a)return b;//// if(!b)return a; return gcd(b,a%b);}int num[MAXN];struct Node{ int l,r; int mx,val; //mx记录最大值,用于剪枝 //val为-1是没有lazy,否则存储需要更新的值v--操作1 //注意因为更新的值是大于等于0的,所以可以这么用}nodes[MAXN*4];void pushup(int rt){ nodes[rt].mx=max(nodes[ls(rt)].mx,nodes[rs(rt)].mx);}void build(int rt, int l, int r){ nodes[rt].l=l; nodes[rt].r=r; nodes[rt].mx=0; nodes[rt].val=-1; if(l == r) { nodes[rt].mx=nodes[rt].val=num[l]; return; } int mid=(l+r)/2; build(ls(rt),l,mid); build(rs(rt),mid+1,r); pushup(rt);}void modify(int rt,int v)//2操作{ if(nodes[rt].mx<=v)return; if(nodes[rt].val!=-1)//仍然更新到段--到仅仅有一种更新lazy标记 { nodes[rt].mx=nodes[rt].val=gcd(nodes[rt].val,v); //nodes[rt].val=-1; return; } modify(ls(rt),v); modify(rs(rt),v); pushup(rt);}void update(int rt, int l, int r,int op,int v){ //找到区间之后,根据操作做更新 //一种操作的话,当找到对应的 //区间(nodes[rt].l==l && nodes[rt].r==r)之后, //只标记而不往下更新,直到下次update到这次才将这次的pushdown //此题中,操作一是赋值,会覆盖操作二,所以直接操作 //如果是操作二,查看之前是不是已经有lazy操作,有的话,先做之前的lazy, //直到达到一个结点,该节点没有做过lazy标记,那么标记这个节点,停止update‘ if(nodes[rt].l==l && nodes[rt].r==r) { if(op==1) { nodes[rt].val=v; nodes[rt].mx=v;//该区间所有的值都变成了v,所以最大值为v } else { modify(rt,v); } return; } //pushdown if(nodes[rt].val!=-1) { //此处把mx也更新了,因为gcd(a,b)<=a&&gcd(a,b)<=b //又因为题目中说了,当要更新的val<num[i]时才更新num[i]为gcd(); // nodes[ls(rt)].mx=nodes[rs(rt)].mx=nodes[rt].val; nodes[ls(rt)].val=nodes[rs(rt)].val=nodes[rt].val; nodes[rt].val=-1; } int mid=(nodes[rt].l+nodes[rt].r)/2; if(r<=mid)update(ls(rt),l,r,op,v); else { if(l>mid) update(rs(rt),l,r,op,v); else { update(ls(rt),l,mid,op,v); update(rs(rt),mid+1,r,op,v); } } pushup(rt);}void dfs(int rt){ if(nodes[rt].l==nodes[rt].r) { num[nodes[rt].l]=nodes[rt].val; return; } if(nodes[rt].val!=-1) { nodes[ls(rt)].val=nodes[rs(rt)].val=nodes[rt].val; nodes[rt].val=-1; } dfs(ls(rt)); dfs(rs(rt));}int main(){ //IN("hdu4902.txt"); int ncase,n,q,l,v,r; int op; scanf("%d",&ncase); while(ncase--) { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&num[i]); build(1,1,n); scanf("%d",&q); while(q--) { scanf("%d%d%d%d",&op,&l,&r,&v); update(1,l,r,op,v); } dfs(1); for(int i=1;i<=n;i++) printf("%d ",num[i]); putchar('\n'); } return 0;}
2 0
- hdu 4902 线段树双标记类型题
- HDU 4902 双标记线段树
- hdu 3397 线段树双标记
- hdu 3397 线段树双标记
- hdu 3954 线段树 (标记)
- HDU 4902 NICE BOAT (线段树+懒标记)
- hdu 4893 线段树 --- 也是两个变 类似双标记
- hdu 3397 线段树+区间合并+懒惰标记 好题
- 线段树单标记,双标记
- hdu 1698 线段树 懒惰标记
- HDU 4339 (线段树字符标记)
- hdu 4578 线段树lazy标记
- hdu 4578 线段树(标记处理)
- 线段树(类似延迟标记) HDU
- 山东省赛题 NEU OJ 1444 线段树双标记
- hdu 3397 Sequence operation (线段树+区间合并+双Lazy标记)
- hdu 1556 Color the ball(线段树+懒惰标记)
- hdu-4587-线段树的区间操作- lazy标记
- POJ 3400 Dropping the stones 深搜,然后加个小优化
- Python爬虫入门教程
- POJ 1002 487-3279 MAP||Sort
- char * a, char ** a, char * a[], char a[][], char * a[][], char ** a[][], char * a [][][], and so on
- 适合国人使用的源代码托管服务空间(本土化的github)
- hdu 4902 线段树双标记类型题
- Copy List with Random Pointer
- Android SDK离线安装方法详解(加速安装)
- 使用autotools生成Makefile
- 黑马程序员 java学习笔记——javaBean
- 求逆元方法总结
- linux基础命令
- EditText属性简介
- DM6437外设