• [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;
    }
  • 相关阅读:
    20160813上午训练记录
    [bzoj 2159]Crash的文明世界
    【娱乐】高端小游戏Manufactoria
    【教程】如何正确的写一个Lemon/Cena的SPJ(special judge)
    [CF]codeforces round#366(div2)滚粗记
    洛谷 [P3265] 装备购买
    POJ 1830 开关问题
    洛谷 [P4035] 球形空间生成器
    BZOJ 2973 入门OJ4798 石头游戏
    洛谷 [P1939] 矩阵加速数列
  • 原文地址:https://www.cnblogs.com/rrsb/p/9489587.html
Copyright © 2020-2023  润新知