5040: 未来研究 dsu on tree

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]);
}

猜你喜欢

转载自blog.csdn.net/baidu_36797646/article/details/80078153