1. 程式人生 > >[8月4日衢州二中] problem C

[8月4日衢州二中] problem C

scan c++ fine nbsp 序列 stat 分塊 ble 依次

題目描述

給出兩個序列{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\n",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\n",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; }

[8月4日衢州二中] problem C