zoukankan      html  css  js  c++  java
  • [8月4日衢州二中] problem C

    题目描述

    给出两个序列{a[i]}、{b[i]},一个排列 p 的权值定义为∑a[i]*b[p[i]]。

    一开始有一个排列 P 作为限制,表示任意与 P 有某一位相同的排列均不合法。 初始时 P[i]=i,有 q 次操作,每次交换 P 中的两个元素。 在每次操作后,求出此时所有合法排列的权值中的最大值。

    输入

    第一行 n,q

    第二行依次给出 a 中元素

    第三行依次给出 b 中元素

    接下来 q 行每行两个数 a、b,表示交换 P[a]、P[b]

    输出

    q 行,每行的输出见题述

    提示

     对于所有数据n<=30000,m<=30000,a和b在10^6范围内。

     分块+插头DP

    #pragma GCC optimize("-Ofast")
    #include<bits/stdc++.h>
    using namespace std;
    #define pii pair<int,int>
    #define N 30007
    #define fi first
    #define se second
    #define LL long long
    pii a[N],b[N];
    int ida[N],idb[N],can[N],x,y,n,q,usd[N],cat,to[16],oz[16],tot,st,ed,L[N],R[N],l,r,belong[N];
    LL dp[N][36],Dp[N][36];
    int Blo,state,will;
    #define max(a,b) (a>b?a:b)
    long long ans;
    int bitcount(int x) {
        if (!x) return 0;
        return bitcount(x-(x&-x))+1;
    }
    void Pre(){
        for (int i=0;i<16;i++)
         if (bitcount(i)==2) to[i]=tot,oz[tot++]=i;
    }
    inline void clear(int l,int r){
        for (int i=l;i<=r;i++)
         for (int j=0;j<36;j++) dp[i][j]=0;
    } 
    void dfs(int x,int leaf,int state,LL oj){
        if (!leaf) {
             st=state>>4;
             ed=state&15;
             if (bitcount(st)!=2||bitcount(ed)!=2) return;
             st=to[st]; ed=to[ed];
             dp[x-1][st*6+ed]=max(dp[x-1][st*6+ed],oj);
             return;
        }
        state<<=1;
        for (int i=0;i<5;i++) {
         if ((state>>i)&1) continue;
         if (idb[can[a[x].se]]==x+2-i) continue;
         dfs(x+1,leaf-1,state|(1<<i),oj+1ll*a[x].fi*b[x+2-i].fi);
        }
    }
    //void Dfs(int st,int x,int leaf,int state,LL oj){
    //  if (!leaf) {
    ////        if ((state&3)) return;
    ////        cerr<<state<<endl;
    //      ed=(state)&15;
    //      if (bitcount(ed)!=2) return;
    //      dp[x-1][st*6+to[ed]]=max(dp[x-1][st*6+to[ed]],oj);
    //      return;
    //  }
    //  state<<=1;
    //  for (int i=0;i<5;i++) {
    //   if ((state>>i)&1) continue;
    //   if (idb[can[a[x].se]]==x+2-i) continue;
    ////     assert(bitcount(state)+1==bitcount(state|(1<<i)));
    //   Dfs(st,x+1,leaf-1,state|(1<<i),oj+1ll*a[x].fi*b[x+2-i].fi);
    //  }
    //}
    void pre(int x){
        l=L[x]; r=R[x];
        clear(l,r);
        dfs(l,4,0,0);
        for (int i=l+4;i<=r;i++) {
            for (int k=0;k<36;k++) {
                st=oz[k/6],ed=oz[k%6];
                if ((ed>>3)!=1) {
                  if (idb[can[a[i].se]]==i-2) continue;
                  state=ed<<1;
                  will=k/6*6+to[state];
                  dp[i][will]=max(dp[i][will],dp[i-1][k]+1ll*a[i].fi*b[i-2].fi);
                 } else {
                    state=(ed-8)<<1;
                    for (int j=0;j<4;j++) {
                     if ((state>>j)&1) continue;
                     if (idb[can[a[i].se]]==i+2-j) continue;
                      state^=1<<j;
                      will=k/6*6+to[state];
                      dp[i][will]=max(dp[i][will],dp[i-1][k]+1ll*a[i].fi*b[i+2-j].fi);
                      state^=1<<j;
                    }
                 }
            }
        }
    } 
    LL sta[701][6],anw;
    void Merge(){
        if (belong[n]==1) {printf("%lld
    ",dp[n][5]); return;}
        memset(sta,0,sizeof sta); anw=0;
        for (int i=0;i<6;i++)  sta[1][i]=dp[R[1]][i];
        for (int i=2;i<belong[n];i++)
         for (int j=0;j<36;j++)
          sta[i][j%6]=max(sta[i-1][to[15-oz[j/6]]]+dp[R[i]][j],sta[i][j%6]);
        for (int i=5;i<36;i+=6)
         anw=max(anw,sta[belong[n]-1][to[15-oz[i/6]]]+dp[n][i]);
     
        printf("%lld
    ",anw);
    }
    signed main() {
        Pre();
        scanf("%d%d",&n,&q);
        for (int i=1;i<=n;i++) scanf("%d",&a[i].fi),a[i].se=i;
        for (int i=1;i<=n;i++) scanf("%d",&b[i].fi),b[i].se=i;
        sort(a+1,a+n+1); sort(b+1,b+n+1);
        for (int i=1;i<=n;i++) ida[a[i].se]=i,idb[b[i].se]=i;
        for (int i=1;i<=n;i++) can[i]=i;
        Blo=max(sqrt(n/6),5.0);
        for (int i=1;i<=n;i++) belong[i]=i/Blo+1; 
        if (n%Blo<4) for (int i=n/Blo*Blo;i<=n;i++) belong[i]--;
        for (int i=1;i<=n;i++) {
            if (R[belong[i]]<i) R[belong[i]]=i;
            if (!L[belong[i]])  L[belong[i]]=i;
        }
    //    for (int i=1;i<=n;i++) belong[i]=1;
    //    L[1]=1; R[1]=n;
    //  for(int i = 1; i <= belong[n]; ++i) cerr << L[i] << ' '<<R[i]<<endl;
        for (int i=1;i<=belong[n];i++)  pre(i); 
    //  Merge(); 
        while (q--) {
          scanf("%d%d",&x,&y);
          swap(can[x],can[y]);
    //    memset(usd,0,sizeof usd);
          if (belong[ida[x]]==belong[ida[y]]) pre(belong[ida[x]]);
          else pre(belong[ida[x]]),pre(belong[ida[y]]);
          Merge();
        } 
        return 0;
    }
  • 相关阅读:
    leetcode 18 4Sum
    leetcode 71 Simplify Path
    leetcode 10 Regular Expression Matching
    leetcode 30 Substring with Concatenation of All Words
    leetcode 355 Design Twitte
    leetcode LRU Cache
    leetcode 3Sum
    leetcode Letter Combinations of a Phone Number
    leetcode Remove Nth Node From End of List
    leetcode Valid Parentheses
  • 原文地址:https://www.cnblogs.com/rrsb/p/9489587.html
Copyright © 2011-2022 走看看