More than 2019 cattle off summer school camp (fourth occasion set)

C-sequence

Meaning of the questions:

Title of length n is given two arrays a, b, determined

analysis:

Standard Solution:

Code:

 (+ Monotone stack segment tree)

#include<iostream>
#include<stack>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cstdio>
using namespace std;
const int MAX=3e6+9;
const int INF=0x3f3f3f3f;
typedef long long ll;
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
int n;
int l[MAX],r[MAX],a[MAX],b[MAX];
ll sum[MAX];
stack<int>st;
struct tree{    //线段树维护前缀和最大最小值 
    ll mx,mn;
}tree[MAX<<2];
void PushUp(int rt)
{
    tree[rt].mx=max(tree[rt<<1].mx,tree[rt<<1|1].mx);
    tree[rt].mn=min(tree[rt<<1].mn,tree[rt<<1|1].mn);
}
void Build(int l,int r,int rt)
{
    if(l==r)
    {
        tree[rt].mx=sum[l];
        tree[rt].mn=sum[l];
        return;
    }
    int m=l+r>>1;
    Build(ls);Build(rs);
    PushUp(rt);
}
ll Query_min(int L,int R,int l,int r,int rt)
{
    ll ans=INF;
    if(L<=l&&r<=R)
        return tree[rt].mn;
    int m=l+r>>1;
    if(L<=m)ans=min(ans,Query_min(L,R,ls));
    if(R>m)ans=min(ans,Query_min(L,R,rs));
    return ans; 
}
ll Query_max(int L,int R,int l,int r,int rt)
{
    ll ans=-INF;
    if(L<=l&&r<=R)
        return tree[rt].mx;
    int m=l+r>>1;
    if(L<=m)ans=max(ans,Query_max(L,R,ls));
    if(R>m)ans=max(ans,Query_max(L,R,rs));
    return ans;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)scanf("%d",&b[i]);
    for(int i=1;i<=n;i++)sum[i]=b[i]+sum[i-1];
    Build(1,n,1);
    a[0]=a[n+1]=-INF;
    for(int i=0;i<=n+1;i++)
    {        
        while(!st.empty()&&a[st.top()]>a[i]) //单调栈维护以每个a[i]为最小值的区间左右端点 
        {
            r[st.top()]=i-1;
            st.pop();
        }
        if(!st.empty())l[i]=st.top()+1;
        st.push(i);
    }
//    for(int i=1;i<=n;i++)cout<<l[i]<<' '<<r[i]<<endl;
    ll ans=-INF;
    for(int i=1;i<=n;i++)
    {
        if(a[i]>=0)
        {
            ll h=(ll)a[i]*(sum[r[i]]-sum[l[i]-1]);
            if(h>ans)
                ans=h;
        }
        else
        {//a[i]为负数 取区间和最小 
            ll mx=Query_max(l[i],i,1,n,1);
            ll mn=Query_min(i,r[i],1,n,1);
            ll h=(ll)a[i]*(mn-mx);
            if(h>ans)ans=h;
        }
    }
    printf("%lld\n",ans);
    return 0;
}
View Code

 

A-meeting

Meaning of the questions:

There is a city, there are n interesting places are numbered 1 ~ n, is now in place x1, x2 ..., xk a man they want

Find a place to meet, at least ask how much time it will take.

analysis:

Standard straightforward solution to a problem, tql

Error: I do not communicate mentally, I feel determined lca between all points, d and then take the maximum points to lca can. But just

Think simple counter-examples can be found, such as a 1-> 22-> 33-> 41-> lca 5 thus found is 1, 1, and 5 is the shortest distance aggregation

3 but in fact brought together in the shortest cost is 2 points 3

Code:

(X1 ~ xk find all points in lca from the furthest point to another point and then find the point of maximum distance, taking half rounded up)

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAX=1e5+9;
struct Edge{
    int to,val,next;
}edge[MAX*2];
int head[MAX],cnt=0;
int deep[MAX],dis[MAX];
int up[MAX][20];
int n,k,a,b,x[MAX];
inline void add(int u,int v,int w)
{
    edge[cnt].val=w;
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
void dfs(int u)
{
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int to=edge[i].to;
        if(up[u][0]==to)continue;
        deep[to]=deep[u]+1;
        dis[to]=dis[u]+edge[i].val;
        up[to][0]=u;
        dfs(to);
    }
}
void init()
{
    for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i<=n;i++)
            up[i][j]=up[up[i][j-1]][j-1];
}
int LCA(int a,int b)
{
    if(deep[a]<deep[b])swap(a,b);
    int d=deep[a]-deep[b];
    for(int i=0;i<20;i++)
        if((1<<i)&d)
            a=up[a][i];
    if(a==b)return a;
    for(int i=19;i>=0;i--)
    {
        if(up[a][i]!=up[b][i])
            a=up[a][i],b=up[b][i];
    }
    return up[a][0];        
}
int get_dis(int a,int b,int lca)
{
    return dis[a]+dis[b]-dis[lca]*2;
}

int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&k);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&a,&b);
        add(a,b,1),add(b,a,1);
    }
    dfs(1);init();

    for(int i=1;i<=k;i++)
        scanf("%d",&x[i]);

    if(k==1)printf("0\n");
    else
    {
        int lca=x[1];
        for(int i=2;i<=k;i++)
            lca=LCA(x[i],lca);
        
        int mx=0,pos,ans=0;    
        for(int i=1;i<=k;i++)        //离所有点lca最远的点 
        {
            if(MX <DIS [X [I]] - DIS [LCA]) 
            { 
                MX = DIS [X [I]] - DIS [LCA]; 
                POS = X [I]; 
            } 
        } 
        for ( int I = . 1 ; I < K =; I ++)         // find the point farthest away, and taking half the distance, rounded up 
        { 
            ANS = max (ANS, (get_dis (POS, X [I], the LCA (POS, X [I])) + . 1 ) / 2 ); 
        } 
        the printf ( " % D \ n- " , ANS); 
    } 

    return  0 ; 
}
View Code

 

Guess you like

Origin www.cnblogs.com/LjwCarrot/p/11299487.html