zoukankan      html  css  js  c++  java
  • 题解 UVA11235 【Frequent values】

    \[\texttt{前言} \]

    \(\quad\)题解中怎么只有莫队和 \(st\) 表的解法(还有一个分块写法)?那么我就来分享一波萌新都可以看懂的线段树题解(我就是萌新),并不算很复杂,但胜在思路简单,主要是好想。

    \[\texttt{题目大意} \]

    \(\quad\)给定一个长为 \(n\) 的上升序列 \(a_i\),并给定 \(q\) 次询问,每次询问给出 \(l,r\) 询问区间 \([l,r]\) 的众数的出现次数。

    \[\texttt{线段树解法} \]

    \(\quad\)因为给定的是有序的序列,每种数都只出现在一段连续的区间内,所以我就想到了线段树求解,以前做过一道类似的题:CF515E Drazil and Park (我的题解)

    \(\quad\)我选择用结构体来保存线段树的信息,\(Max\) 表示这个区间中出现次数最多的数的个数,\(ll\) 表示从最左边开始连续的数的数量,\(rr\) 表示从最右边开始的数的数量,\(l\) 表示区间最左端的数的值,\(r\) 表示区间最右端的数的值。

    \(\quad\)其中 \(ll\)\(rr\) 在两个子区间合并的时候可以发挥作用,因为这样可以连接左右两个子区间,这个在很多区间问题上都可以巧妙运用。

    \(\quad\)其他解释都在注释里,个人认为很好理解,下面是核心代码,建树和在线询问操作。

    struct node{
    	int Max,ll,rr,l,r;
    }t[N<<2];
    
    il void build(int k,int l,int r)//建树
    {
    	if(l==r){t[k].Max=t[k].ll=t[k].rr=1;t[k].l=t[k].r=a[l]=read();return;}//初始化
    	int mid=l+r>>1;
    	build(k<<1,l,mid);build(k<<1|1,mid+1,r);
    	if(a[l]==a[mid+1])t[k].ll=mid-l+1+t[k<<1|1].ll;//左子区间都是一样的值的情况就合并
       else t[k].ll=t[k<<1].ll;
    	if(a[mid]==a[r])t[k].rr=r-mid+t[k<<1].rr;//右子区间都是一样的值的情况就合并
       else t[k].rr=t[k<<1|1].rr;
    	t[k].Max=max(t[k<<1].Max,t[k<<1|1].Max);//更新
    	t[k].l=t[k<<1].l;t[k].r=t[k<<1|1].r;//更新
    	if(a[mid]==a[mid+1])t[k].Max=max(t[k].Max,t[k<<1].rr+t[k<<1|1].ll);//左右子区间相邻的值相同时可以合并
    }
    
    il node query(int k,int l,int r,int x,int y)//返回的是结构体node
    {
    	if(l>=x&&r<=y)return t[k];
    	int mid=l+r>>1;
    	if(y<=mid)return query(k<<1,l,mid,x,y);//答案只在左区间
    	if(x>mid)return query(k<<1|1,mid+1,r,x,y);//答案只在右区间
    	node tmp1=query(k<<1,l,mid,x,y),tmp2=query(k<<1|1,mid+1,r,x,y),ans;//答案横跨左右区间要格外注意
    	ans.Max=max(tmp1.Max,tmp2.Max);//更新过程和上面的建树一样
    	ans.ll=tmp1.ll;ans.rr=tmp2.rr;
    	ans.l=tmp1.l;ans.r=tmp2.r;
    	if(tmp1.l==tmp2.l)ans.ll=tmp1.ll+tmp2.ll;//左子区间都是一样的值的情况就合并
    	if(tmp1.r==tmp2.r)ans.rr=tmp1.rr+tmp2.rr;//右子区间都是一样的值的情况就合并
    	if(a[mid]==a[mid+1])ans.Max=max(ans.Max,tmp1.rr+tmp2.ll);//左右子区间相邻的值相同时可以合并
    	return ans;
    }
    

    \(\quad\)完整代码在剪贴板里。

    \[\texttt{后话} \]

    \(\quad\)对了此题还有多倍经验,都是一样的:

  • 相关阅读:
    大学的最后时光---我的毕设日记(二)
    大学的最后时光---我的毕设日记(一)
    记公司同事的一次集体活动
    ssh框架基本原理
    plsql基本操作记录
    eclipse快捷键。
    面向对象的特性:封装继承多态
    设置label中的对齐方式
    pixmap和label设置图片自适应大小
    类的继承
  • 原文地址:https://www.cnblogs.com/FarkasW/p/15463153.html
Copyright © 2011-2022 走看看