洛谷P3567 KUR-Couriers [POI2014] 主席树/莫队
正解:主席树/莫队
解题报告:
这题好像就是个主席树板子题的样子,,,?
毕竟,主席树的最基本的功能就是,维护一段区间内某个数字的个数
但是毕竟是刚get到主席树,然后之前做的一直是第k大,这个是维护区间内数字个数,题目类型不一样,所以还是积累一下这个题型和对应的方法QAQ
顺便也水一发题解
所以还是写下这题
首先不难想到对于[l,r]的点直接把r的树和l-1的树做差就可以得到
这样现在就相当于是得到了一棵线段树
那肯定就是维护这个区间的所有数字的出现次数(,,,我发现我这里出现了两个意义不同的区间,星趴我后面解释一下)
显然出现的次数总和sum是已知不变的,不可能存在l和r都>=sum/2(,,,哦其实存在极端情况的然而不要在意这种细节,,,差不多做法QAQ!)
所以每次就往出现次数>=sum/2的区间跑,如果跑到叶子节点了,就说明存在,如果跑着跑着发现,两个区间都不满足>=sum/2,说明GG了,就不存在
然后就做完辣!
然后说下两个区间
第一个是最前面说,"首先不难想到对于[l,r]的点直接把r的树和l-1的树做差就可以得到",这里指的是[l,r]这个询问
第二个是第三行"那肯定就是维护这个区间的所有数字的出现次数"以及之后所有的关于区间的说法,指的都是序列上的区间
代码等下放QAQ
另外说下!这题还有个!莫队做法!虽然复杂度不对!但是能过去!但是我不想打了反正莫队基本上实现都很简单,懒得写了QAQ
#include<bits/stdc++.h> using namespace std; #define il inline #define rg register #define gc getchar() #define rp(i,x,y) for(rg int i=x;i<=y;++i) const int N=1000000; int n,m,a[N],st[N],tot,nod_cnt,rt[N],r,l; struct sgtr{int l,r,ls,rs,sz,name;}tr[N<<3]; il int read() { rg char ch=gc;rg int x=0;rg bool y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } il void build(int x,int l,int r) { ++nod_cnt;tr[x].l=l,tr[x].r=r;tr[x].name=l; if(l==r)return; tr[x].ls=nod_cnt+1;build(tr[x].ls,l,(l+r)>>1);tr[x].rs=nod_cnt+1;build(tr[x].rs,((l+r)>>1)+1,r);return; } il void modify(int x,int dat) { ++nod_cnt;tr[nod_cnt]=tr[x];++tr[nod_cnt].sz; if(tr[nod_cnt].l==tr[nod_cnt].r)return; int mid=(tr[nod_cnt].l+tr[nod_cnt].r)>>1; if(dat<=mid){tr[nod_cnt].ls=nod_cnt+1;modify(tr[x].ls,dat);}else{tr[nod_cnt].rs=nod_cnt+1;modify(tr[x].rs,dat);} } il int query(int nw1,int nw2,int len) { if(tr[nw1].l==tr[nw1].r)return tr[nw1].name; int tmp1=-1; if((tr[tr[nw2].ls].sz-tr[tr[nw1].ls].sz)*2>len)tmp1=query(tr[nw1].ls,tr[nw2].ls,len); if(tmp1!=-1)return tmp1; if((tr[tr[nw2].rs].sz-tr[tr[nw1].rs].sz)*2>len)tmp1=query(tr[nw1].rs,tr[nw2].rs,len); return tmp1; } int main() { // freopen("kc.in","r",stdin);freopen("kc.out","w",stdout); n=read();m=read();rp(i,1,n)a[i]=st[i]=read();sort(st+1,st+1+n);tot=unique(st+1,st+1+n)-st-1;rp(i,1,n)a[i]=lower_bound(st+1,st+1+tot,a[i])-st; rt[0]=1;build(1,1,tot); rp(i,1,n){rt[i]=nod_cnt+1;modify(rt[i-1],a[i]);} rp(i,1,m){l=read(),r=read();int tmp=query(rt[l-1],rt[r],r-l+1);if(tmp==-1)printf("0\n");else printf("%d\n",st[tmp]);} return 0; }