Description
GX国未来研究的第一人–Hfu教授,最近获得了一份被认为是未来LY国的住民写下的日记。Hfu教授为了通过这份日记来研究未来LY国的生活,开始着手调查日记中记载的事件。日记中记录了连续N天发生的时间,大约每天发生一件。事件有种类之分。第i天(1<=i<=N)发生的事件的种类用一个整数Xi表示,Xi越大,事件的规模就越大。Hfu教
授决定用如下的方法分析这些日记:
1. 选择日记中连续的一些天作为分析的时间段
2. 事件种类t的重要度为t*(这段时间内为t的事件数)
3. 计算出所有事件种类的重要度,输出其中的最大值
现在你被要求制作一个帮助Hfu教授分析的程序,每次给出分析的区间,你需要输出重要度的最大值。
题解:
dsu on tree的裸题,来复习一发。这题与历史研究的不同之处就是询问间的关系只有包含与相离(大概意思理解就好),所以可以把询问建成一棵树,然后dsu即可。至于建边可以用在单调栈上二分实现。
代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=550010;
const int Maxq=400010;
const int inf=2147483647;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
int n,Q,to[Maxn],a[Maxn],id=0;
struct Node{int x,id;}A[Maxn];
bool cmp1(Node a,Node b){return a.x<b.x;}
struct Query{int l,r,id;}q[Maxq];
bool cmp2(Query a,Query b)
{
if(a.l!=b.l)return a.l<b.l;
return a.r>b.r;
}
int sta[Maxn],top=0,root;
struct Edge{int y,next;}e[Maxq];
int last[Maxq],len=0;
void ins(int x,int y)
{
// printf("%d %d\n",x,y);
int t=++len;e[t].y=y;e[t].next=last[x];last[x]=t;
}
int son[Maxn];
int get_son(int x)
{
int sz=1,mx=0;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
int t=get_son(y);
sz+=t;
if(t>mx)mx=t,son[x]=y;
}
return sz;
}
int cnt[Maxn];LL ans[Maxq],tans;bool mark[Maxn];
void work(int x,int op)
{
if(son[x]&&op==1)
{
int y=son[x];
for(int i=q[x].l;i<q[y].l;i++)
{
cnt[a[i]]+=op;
tans=max(tans,(LL)cnt[a[i]]*to[a[i]]);
}
for(int i=q[y].r+1;i<=q[x].r;i++)
{
cnt[a[i]]+=op;
tans=max(tans,(LL)cnt[a[i]]*to[a[i]]);
}
}
else
{
for(int i=q[x].l;i<=q[x].r;i++)
{
cnt[a[i]]+=op;
tans=max(tans,(LL)cnt[a[i]]*to[a[i]]);
}
}
}
void dfs(int x,bool keep)
{
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(y==son[x])continue;
dfs(y,false);
}
if(son[x])dfs(son[x],true);
if(x==Q+1)return;
work(x,1);
ans[q[x].id]=tans;
if(!keep)work(x,-1),tans=0;
}
int main()
{
n=read(),Q=read();
for(int i=1;i<=n;i++)A[i].x=read(),A[i].id=i;
sort(A+1,A+1+n,cmp1);
A[0].x=0;
for(int i=1;i<=n;i++)
{
if(A[i].x!=A[i-1].x)id++;
a[A[i].id]=id;
to[id]=A[i].x;
}
for(int i=1;i<=Q;i++)q[i].l=read(),q[i].r=read(),q[i].id=i;
sort(q+1,q+1+Q,cmp2);
root=Q+1;
for(int i=1;i<=Q;i++)
{
while(top&&q[sta[top]].r<q[i].r)top--;
if(!top)ins(root,i);
else
{
int l=1,r=top;
while(l<=r)
{
int mid=l+r>>1;
if(q[sta[mid]].r>=q[i].r)l=mid+1;
else r=mid-1;
}
ins(sta[l-1],i);
}
sta[++top]=i;
}
get_son(Q+1);
dfs(Q+1,true);
for(int i=1;i<=Q;i++)printf("%lld\n",ans[i]);
}