codeforces 318 D. Bear and Cavalry


题目描述:

D. Bear and Cavalryios

time limit per test:3 secondsc++

memory limit per test:256 megabytesweb

input:standard inputide

output:standard outputsvg

Would you want to fight against bears riding horses? Me neither.spa

Limak is a grizzly bear. He is general of the dreadful army of Bearland. The most important part of an army is cavalry of course..net

Cavalry of Bearland consists of n warriors and n horses. i-th warrior has strength wi and i-th horse has strength hi. Warrior together with his horse is called a unit. Strength of a unit is equal to multiplied strengths of warrior and horse. Total strength of cavalry is equal to sum of strengths of all n units. Good assignment of warriors and horses makes cavalry truly powerful.code

Initially, i-th warrior has i-th horse. You are given q queries. In each query two warriors swap their horses with each other.regexp

General Limak must be ready for every possible situation. What if warriors weren’t allowed to ride their own horses? After each query find the maximum possible strength of cavalry if we consider assignments of all warriors to all horses that no warrior is assigned to his own horse (it can be proven that for n ≥ 2 there is always at least one correct assignment).xml

Note that we can’t leave a warrior without a horse.

Input

The first line contains two space-separated integers, n and q (2 ≤ n ≤ 30 000, 1 ≤ q ≤ 10 000).

The second line contains n space-separated integers, w1, w2, …, wn (1 ≤ wi ≤ 106) — strengths of warriors.

The third line contains n space-separated integers, h1, h2, …, hn (1 ≤ hi ≤ 106) — strengths of horses.

Next q lines describe queries. i-th of them contains two space-separated integers ai and bi (1 ≤ ai, bi ≤ n, ai ≠ bi), indices of warriors who swap their horses with each other.

Output

Print q lines with answers to queries. In i-th line print the maximum possible strength of cavalry after first i queries.

题解:

好题。首先是一个贪心性质:咱们从大到小排序,若是没有限制,那么确定是按照顺序来配对是结果最大的。可是如今有一些限制的关系。那么怎么办呢?咱们探索一下。咱们设dp【i】,表示i是最后一个,解决完dp【i】的值。那么推i:若是wi能够和hi匹配,那么咱们直接让wi和hi匹配就是最好的。若是wi和hi不能够,那么咱们让wi-1和hi以及wi和hi-1来匹配,这样必定是最好的。可是有一个问题,可能wi-2和hi-2不能匹配,因此可能i会涉及到i-2. 可是有一个重要的性质,咱们发现i最多只会涉及到i-2,再往前就必定能够经过调整来不那么远。 那么咱们最裸的dp就是:dp【i】,而后o(3)的暴力转移。
可是这道题目能够用线段树来加速。毕竟每一次询问只改了不多的值。主要想明白两端区间怎么合并,就是怎么pushUp。怎么才能合并呢?dp的向前延伸和向后延伸都是2.l mid mid+1 r 这两个怎么合并?看mid+1最多会受到前面多少的影响.mid,mid-1. 那么暴力枚举mid+1和哪3(也多是2或者本身)个发生关系。因此咱们只须要把l到mid的后面的2个元素可能性的去掉多维护一些东西就好了。 咱们维护一个3*3的矩阵。 0、一、2分别表明去掉前、后0.1.2个元素以后的dp值。这样在合并的时候只须要大约3*3*3的暴力合并就好了。
有一个特殊的地方就是:当区间长度小于4的时候会比较麻烦,所以咱们区间小于8以后就再也不分,而是改用暴力。

重点:

(1)贪心的想乘
(2)有条件限制的时候不用直接想,能够转成dp简化思惟
(3)发现性质,i只会最多和i-2发生关系
(4)每次只修改一点,而且dp的后效性很小,能够用线段树加速

代码:

#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <ctype.h>
#include <limits.h>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#define CLR(a) memset(a, 0, sizeof(a))
#define REP(i, a, b) for(ll i = a;i < b;i++)
#define REP_D(i, a, b) for(ll i = a;i <= b;i++)

typedef long long ll;

using namespace std;

const ll maxn = 30000+100;
const ll MAX_NODE = maxn*4 + 10;

ll n, q;

struct info
{
    ll no, s, wno;
    info(ll _no = 0, ll _s = 0, ll _wno = 0)
    {
        no = _no;
        s = _s;
        wno = _wno;
    }
};
info h[maxn], w[maxn];
ll posH[maxn], posW[maxn];
ll f[maxn];
ll tree[MAX_NODE][3][3];

ll dp(ll l, ll r)
{
    f[l-1] = 0;
    for(ll i = l; i<=r; i++)
        f[i] = -1;
    for(ll i = l; i<=r; i++)
    {
        ll j = i;
        if(j>=l&&f[j-1]!=-1&&w[i].no!=h[j].no)
        {
            f[i] =max(f[i], f[j-1]+(ll)w[i].s*(ll)h[j].s);
        }
        j--;
        if(j>=l&&f[j-1]!=-1)
        {
            if(w[i].no!=h[j].no&&w[j].no!=h[i].no)
                f[i] = max(f[i], f[j-1]+(ll)w[i].s*(ll)h[j].s+(ll)w[j].s*(ll)h[i].s);
        }
        j--;
        if(j>=l&&f[j-1]!=-1)
        {
            if(w[j].no!=h[j+1].no&&w[j+1].no!=h[j+2].no&&w[i].no!=h[j].no)
                f[i] = max(f[i], f[j-1]+(ll)w[j].s*(ll)h[j+1].s+(ll)w[j+1].s*(ll)h[j+2].s+(ll)w[i].s*(ll)h[j].s);
            if(w[j].no!=h[i].no&&w[j+1].no!=h[j].no&&w[i].no!=h[j+1].no)
                f[i] = max(f[i], f[j-1]+(ll)w[j].s*(ll)h[i].s+(ll)w[j+1].s*(ll)h[j].s+(ll)w[i].s*(ll)h[j+1].s);
        }
    }
    return f[r];
}
void pushUp(ll rt, ll l, ll r)//下面的都已经好了.且必定有下面的
{
    ll mid = ((l + r)>>1), lRt = (rt<<1), rRt = ((rt<<1)|1);
    if(mid-l+1<4||r-mid<4)
    {
        for(ll i = 0; i<=2; i++)
        {
            for(ll j = 0; j<=2; j++)
            {
                ll tmp = dp(l+i, r-j);
                tree[rt][i][j] = tmp;
            }
        }
    }
    else
    {
        for(ll i = 0; i<=2; i++)
            for(ll j = 0; j<=2; j++)
                tree[rt][i][j]=-1;
        for(ll xa = 0; xa<=2; xa++)
        {
            for(ll ya = 0; ya<=2; ya++)
            {
                if(tree[lRt][xa][ya]!=-1)
                {
                    for(ll xb=0; xb+ya<=3&&xb<=2; xb++)
                    {
                        for(ll yb = 0; yb<=2; yb++)
                        {
                            if(tree[rRt][xb][yb]!=-1)
                            {
                                ll &key = tree[rt][xa][yb];
                                ll a = tree[lRt][xa][ya], b = tree[rRt][xb][yb];
                                if(ya==0&&xb==0)
                                    key = max(key, a+b);
                                if(ya==0||xb==0)
                                    continue;
                                if(ya==1&&xb==1)
                                {
                                    if(w[mid].no!=h[mid+1].no&&w[mid+1].no!=h[mid].no)
                                        key = max(key, a+b+(ll)w[mid].s*(ll)h[mid+1].s+(ll)w[mid+1].s*(ll)h[mid].s);
                                }
                                if((ya==1&&xb==2)||(ya==2&&xb==1))
                                {
                                    ll i = mid - ya+1;
                                    ll j = i+1;
                                    ll k = j+1;
                                    if(w[i].no!=h[j].no&&w[j].no!=w[k].no&&w[k].no!=h[i].no)
                                        key = max(key, a+b+(ll)w[i].s*(ll)h[j].s+(ll)w[j].s*(ll)h[k].s+(ll)w[k].s*(ll)h[i].s);
                                    if(w[i].no!=w[k].no&&w[j].no!=h[i].no&&w[k].no!=h[j].no)
                                        key = max(key, a+b+(ll)w[i].s*(ll)h[k].s+(ll)w[j].s*(ll)h[i].s+(ll)w[k].s*(ll)h[j].s);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

void dfs(ll rt, ll l, ll r)
{
    if(r-l+1 < 4)
        return;
    ll mid = ((l + r)>>1), lRt = (rt<<1), rRt = ((rt<<1)|1);
    dfs(lRt, l, mid);
    dfs(rRt, mid+1, r);
    pushUp(rt, l, r);
}
void initail()
{
    dfs(1, 1, n);
}

void change(ll a, ll b, ll c, ll d, ll rt, ll l, ll r)
{
    if(r - l + 1< 4)
        return;
    ll mid = ((l + r)>>1), lRt = (rt<<1), rRt = ((rt<<1)|1);
    if((a>=l&&a<=mid)||(b>=l&&b<=mid)||(c>=l&&c<=mid)||(d>=l&&d<=mid))
    {
        change(a, b, c, d, lRt, l, mid);
    }
    if((a>=mid+1&&a<=r)||(b>=mid+1&&b<=r)||(c>=mid+1&&c<=r)||(d>=mid+1&&d<=r))
    {
        change(a, b, c, d, rRt, mid + 1, r);
    }
    pushUp(rt, l, r);//向上push
}

void solve()
{
    initail();
    while(q--)
    {
        ll a, b;
        scanf("%I64d%I64d", &a, &b);
        swap(w[posW[a]].no, w[posW[b]].no);
        if(n>=4)
        {
            change(posW[a], posW[b], posH[w[posW[a]].no], posH[w[posW[b]].no], 1, 1, n);
            printf("%I64d\n", tree[1][0][0]);
        else
        {
            printf("%I64d\n", dp(1, n));
        }
    }
}

bool cmp(info a, info b)
{
    return a.s < b.s;
}
int main()
{
    freopen("4Din.txt", "r", stdin);
    //freopen("4Dout.txt", "w", stdout);
    while(scanf("%I64d%I64d", &n, &q)!=EOF)
    {
        for(ll i = 1; i<=n; i++)
        {
            scanf("%I64d", &w[i].s);
            w[i].no = i;
            w[i].wno = i;
        }
        for(ll i = 1; i<=n; i++)
        {
            scanf("%I64d", &h[i].s);
            h[i].no = i;
        }
        sort(w+1, w+1+n, cmp);
        sort(h+1, h+1+n, cmp);
        for(ll i = 1; i<=n; i++)
        {
            posW[w[i].wno] = i;
            posH[h[i].no] = i;
        }
        solve();
    }
    return 0;
}

本文分享 CSDN - ruclion。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索