• BZOJ2158 : Crash 的旅行计划


    A类数据:

    $n,qleq1000$

    修改:$O(1)$直接改

    查询:$O(n)$BFS

    B类数据:

    $n,qleq100000$,保证是一条链

    用线段树维护区间最大前缀、后缀和

    修改:$O(log n)$

    查询:答案为max([1,x]的最大后缀和,[x,n]的最大前缀和),$O(log n)$

    C类数据:

    $n,qleq100000$,保证以1为根时树高不超过40

    设val[x]为从x向下走的最大和,val[x]=max(val[son[x]],0)+a[x]

    每个点维护一棵平衡树,平衡树里每个节点存孩子id以及该孩子的val

    预处理:$O(nlog n)$

    修改:修改a[x],然后从x开始把它的所有父亲都修改掉,$O(dlog n)$

    查询:从x开始往上走,设sum[x]为到x时的总和(包括x),ans=max(sum[x]+x平衡树中不是从之前儿子走过来的最大值),$O(dlog n)$

    总时间复杂度:$O((n+qd)log n)$

    #include<cstdio>
    #include<set>
    #include<algorithm>
    #define P make_pair
    #define T pair<int,int>
    #define N 100010
    #define M 200010
    using namespace std;
    struct qq{int k,x,y;}op[N];
    int n,m;
    int a[N],g[N],nxt[N<<1],v[N<<1],ed;
    inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
    namespace subtask1{
    int q[N],h,t,vis[N],sum[N];
    inline int cal(int x){
      int ans=a[x],i;
      for(i=1;i<=n;i++)vis[i]=0;
      q[h=t=1]=x;vis[x]=1;sum[x]=a[x];
      while(h<=t)for(i=g[x=q[h++]];i;i=nxt[i])if(!vis[v[i]])vis[q[++t]=v[i]]=1,ans=max(ans,sum[v[i]]=sum[x]+a[v[i]]);
      return ans;
    }
    inline void work(){
      for(int i=1;i<m;i++)if(op[i].k)a[op[i].x]=op[i].y;
      else printf("%d
    ",cal(op[i].x));
    }
    }
    namespace subtask2{
    struct msg{int ml,mr,sum;msg(){ml=mr=sum=0;}msg(int x){ml=mr=sum=x;}
    inline msg operator+(const msg b){
      msg c;
      c.sum=sum+b.sum;
      c.ml=max(ml,sum+b.ml);
      c.mr=max(b.mr,b.sum+mr);
      return c;
    }
    }val[M];
    int l[M],r[M],tot;
    void build(int c,int d){
      int x=++tot;
      if(c==d){val[x]=msg(a[c]);return;}
      int mid=(c+d)>>1;
      l[x]=tot+1;build(c,mid);
      r[x]=tot+1;build(mid+1,d);
      val[x]=val[l[x]]+val[r[x]];
    }
    void change(int x,int a,int b,int c,int p){
      if(a==b){val[x]=msg(p);return;}
      int mid=(a+b)>>1;
      if(c<=mid)change(l[x],a,mid,c,p);else change(r[x],mid+1,b,c,p);
      val[x]=val[l[x]]+val[r[x]];
    }
    msg ask(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d)return val[x];
      int mid=(a+b)>>1;
      if(d<=mid)return ask(l[x],a,mid,c,d);
      if(c>mid)return ask(r[x],mid+1,b,c,d);
      return ask(l[x],a,mid,c,d)+ask(r[x],mid+1,b,c,d);
    }
    inline void work(){
      build(1,n);
      for(int i=1;i<m;i++)if(op[i].k)change(1,1,n,op[i].x,op[i].y);
      else printf("%d
    ",max(ask(1,1,n,1,op[i].x).mr,ask(1,1,n,op[i].x,n).ml));
    }
    }
    namespace subtask3{
    int f[N],val[N];
    set<T,greater<T> >b[N];
    void dfs(int x,int pre){
      f[x]=pre;b[x].insert(P(0,0));
      for(int i=g[x];i;i=nxt[i])if(v[i]!=pre)dfs(v[i],x),b[x].insert(P(val[v[i]],v[i]));
      val[x]=b[x].begin()->first+a[x];
    }
    inline void change(int x,int p){
      int old=val[x],y=x;
      a[x]=p;
      val[x]=b[x].begin()->first+a[x];
      while(f[x]){
        b[f[x]].erase(P(old,y));
        b[f[x]].insert(P(val[y],y));
        old=val[f[x]],y=f[x];
        val[f[x]]=b[f[x]].begin()->first+a[f[x]];
        x=f[x];
      }
    }
    inline int ask(int x){
      int ans=val[x],sum=a[x],y=x;
      x=f[x];
      while(x){
        sum+=a[x];
        b[x].erase(P(val[y],y));
        ans=max(ans,sum+b[x].begin()->first);
        b[x].insert(P(val[y],y));
        y=x;
        x=f[x];
      }
      return ans;
    }
    inline void work(){
      dfs(1,0);
      for(int i=1;i<m;i++)if(op[i].k)change(op[i].x,op[i].y);
      else printf("%d
    ",ask(op[i].x));
    }
    }
    int main(){
      char c;int L,now,tmp,A,B,Q,i;
      scanf("%c%d%d%d%d%d%d%d",&c,&n,&m,&L,&now,&A,&B,&Q);
      for(i=1;i<=n;i++){
        now=(now*A+B)%Q,tmp=now%10000;
        now=(now*A+B)%Q;
        if(now*2<Q)tmp*=-1;
        a[i]=tmp;
      }
      for(i=1;i<n;i++){
        now=(now*A+B)%Q;
        tmp=(i<L)?i:L;
        add(i-now%tmp,i+1);add(i+1,i-now%tmp);
      }
      for(i=1;i<m;i++){
        now=(now*A+B)%Q;
        if(now*3<Q){
          now=(now*A+B)%Q;
          op[i].x=now%n+1;
        }else{
          now=(now*A+B)%Q,tmp=now%10000;
          now=(now*A+B)%Q;
          if(now*2<Q)tmp*=-1;
          now=(now*A+B)%Q;
          op[i].k=1,op[i].x=now%n+1,op[i].y=tmp;
        }
      }
      if(c=='A')subtask1::work();
      if(c=='B')subtask2::work();
      if(c=='C')subtask3::work();
      return 0;
    }
    

      

     

  • 相关阅读:
    队列(顺序存储结构)
    2015计划
    iframe子窗口父窗口方法调用和元素获取
    Ajax关于重定向
    Java国际化资源文件的选择
    eclipse自动部署web应用程序到tomcat webapps
    从给定字符串结尾获取指定字节长度的字符串
    Winform的一些不知道啥东西
    C# 2008核心编程 2013-09-14
    C# 2008核心编程 2013-09-10
  • 原文地址:https://www.cnblogs.com/clrs97/p/4403250.html
Copyright © 2020-2023  润新知