zoukankan      html  css  js  c++  java
  • Codeforces Round #318(Div. 1) 573 D. Bear and Cavalry【dp+矩阵+线段树优化】

    D. Bear and Cavalry
    time limit per test
    3 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

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

    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.

    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.

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

    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).

    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 0001 ≤ 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 ≤ nai ≠ 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.

    Examples
    input
    4 2
    1 10 100 1000
    3 7 2 5
    2 4
    2 4
    
    output
    5732
    7532
    
    input
    3 3
    7 11 5
    3 2 1
    1 2
    1 3
    2 3
    
    output
    44
    48
    52
    
    input
    7 4
    1 2 4 8 16 32 64
    87 40 77 29 50 11 18
    1 5
    2 7
    6 2
    5 6
    
    output
    9315
    9308
    9315
    9315
    
    Note

    Clarification for the first sample:

    Warriors: 1 10 100 1000

    Horses:   3  7  2    5 

    After first query situation looks like the following:

    Warriors: 1 10 100 1000

    Horses:   3  5  2    7 

    We can get 1·2 + 10·3 + 100·7 + 1000·5 = 5732 (note that no hussar takes his own horse in this assignment).

    After second query we get back to initial situation and optimal assignment is 1·2 + 10·3 + 100·5 + 1000·7 = 7532.

    Clarification for the second sample. After first query:

    Warriors:  7 11 5

    Horses:    2  3 1

    Optimal assignment is 7·1 + 11·2 + 5·3 = 44.

    Then after second query 7·3 + 11·2 + 5·1 = 48.

    Finally 7·2 + 11·3 + 5·1 = 52.



    题意:给出n个战士和他们各自的n批马,我们可以把马换给别的战士,但是都得换(即战士不能拥有原来的马),我们要每个战士乘以给他换的那个马的和最大。q次询问,每次把2个战士的马交换,输出和最大的答案。

    思路:首先如果没有限制,那么根据排序不等式,肯定按顺序匹配战士和马最好。但是现在有了战士不能和自己的马匹配的限制。

    于是就有了一个重要的性质:最优匹配的前提下,排序后第i号战士只会与[i-2,i+2]号马匹配

    (证明:

    设有一种情况i对应i+3 
    i—–(i+3) 
    i+1—(i+2) 
    i+2—(i) 
    i+3—(i+1) 
    那么,对于i,i+1来说,必定在(i–i+2),(i+1–i+3)中有一个限制必选,否则交换i,i+1更优 
    同理,(i–i)(i+2–i+3),(i–i+1)(i+3–i+3)中有一个限制比选 
    发现与限制是一组排列不符,而且i对应i+2时只有(i-i+2)(i+1-i)(i+2-i+1)这种可能

    于是就可以DP了,

    fi表示前i个点匹配的答案。 
    那么

    fi=maxfi1+aibifi2+aibi1+ai1bifi3+aibi1+ai1bi2+ai2bifi3+aibi2+ai1bi+ai2bi1

    这个转移画画图就可以得到。 
    这样就可以O(n2),稍微常数优化一下就可以过。

    #include <iostream>  
    #include <cstdio>  
    #include <cstring>  
    #include <algorithm>  
    #include <cmath>  
    #include <queue>  
    #include <string>  
    #include <map>  
    #include <cstring>  
    #define INF 0x3f3f3f3f  
    #define ms(x,y) memset(x,y,sizeof(x))  
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int, int> P;
    
    const int maxn = 30010;
    const int mod = 998244353;
    
    #define lson l,m,rt<<1  
    #define rson m+1,r,rt<<1|1  
    
    struct node {
    	ll v;
    	int id;
    };
    
    bool cmp(node a, node b)
    {
    	return a.v < b.v;
    }
    
    int posa[maxn], posb[maxn], ban[maxn];
    ll w1[maxn], w2[maxn], w3[maxn], f[maxn];
    node a[maxn], b[maxn];
    
    void cal(int i)
    {
    	w1[i] = w2[i] = w3[i] = -INF;
    	ll t1 = -INF, t2 = -INF;
    	if (i >= 1 && ban[i] != i) w1[i] = a[i].v*b[i].v;
    	if (i >= 2 && ban[i] != i - 1 && ban[i - 1] != i) w2[i] = a[i].v*b[i - 1].v + a[i - 1].v*b[i].v;
    	if (i >= 3 && ban[i] != i - 2 && ban[i - 1] != i&&ban[i - 2] != i - 1) t1 = a[i].v*b[i - 2].v + a[i - 1].v*b[i].v + a[i - 2].v*b[i - 1].v;
    	if (i >= 3 && ban[i] != i - 1 && ban[i - 1] != i - 2 && ban[i - 2] != i) t2 = a[i].v*b[i - 1].v + a[i - 1].v*b[i - 2].v + a[i - 2].v*b[i].v;
    	w3[i] = max(t1, t2);
    }
    
    int main()
    {
    	int n, q;
    	cin >> n >> q;
    	for (int i = 1; i <= n; i++)
    	{
    		cin >> a[i].v;
    		a[i].id = i;
    	}
    	for (int i = 1; i <= n; i++)
    	{
    		cin >> b[i].v;
    		b[i].id = i;
    	}
    	sort(a + 1, a + n + 1, cmp);
    	sort(b + 1, b + n + 1, cmp);
    	for (int i = 1; i <= n; i++)
    	{
    		posa[a[i].id] = i;
    		posb[b[i].id] = i;
    	}
    	for (int i = 1; i <= n; i++)
    	{
    		ban[i] = posb[a[i].id];
    	}
    	for (int i = 1; i <= n; i++)
    	{
    		cal(i);
    	}
    	for (int k = 0; k < q; k++)
    	{
    		int x, y;
    		cin >> x >> y;
    		x = posa[x], y = posa[y];
    		swap(ban[x], ban[y]);
    		for (int i = max(1, x - 5); i <= min(n, x + 5); i++) cal(i);
    		for (int i = max(1, y - 5); i <= min(n, y + 5); i++) cal(i);
    		f[0] = 0;
    		for (int i = 1; i <= n; i++)
    		{
    			f[i] = f[i - 1] + w1[i];
    			if (i >= 2) f[i] = max(f[i], f[i - 2] + w2[i]);
    			if (i >= 3) f[i] = max(f[i], f[i - 3] + w3[i]);
    		}
    		cout << f[n] << endl;
    	}
    	return 0;
    }
    

    但是有更高效的做法 

    fi,j表示前i个,前i-j个已经被匹配了的答案

    那么

    fi,0=maxfi1,0+aibifi1,1+aibi1+ai1bifi1,2+aibi1+ai1bi2+ai2bifi1,2+aibi2+ai1bi+ai2bi1

    fi,1=fi1,0

    fi,2=fi1,1

    这个转移可以被描述成矩阵

    aibiaibi1+ai1bimax{aibi1+ai1bi2+ai2biaibi2+ai1bi+ai2bi1}0infinfinf0inf

    因为矩乘满足结合律,所以可以用线段树维护

    (未完待续)


    Fighting~
  • 相关阅读:
    web前端知识体系大全【欢迎补充】
    ESA2GJK1DH1K基础篇: 阿里云物联网平台: 云平台显示单片机采集的温湿度数据,控制设备继电器(基于ESP8266,AT指令TCP_MQTT通信)(V0.1)
    ESA2GJK1DH1K基础篇: 阿里云物联网平台: 使用阿里云物联网平台提供的物理模型Topic通信控制(ESP8266,TCP透传指令)
    ESA2GJK1DH1K基础篇: 阿里云物联网平台: 使用阿里云物联网平台提供的自定义Topic通信控制(ESP8266,TCP透传指令)
    ESA2GJK1DH1K基础篇: 关于各大物联网平台的MQTT通信
    ESA2GJK1DH1K微信小程序篇: 小程序连接MQTT简单的Demo
    Android 开发基础入门: Android Studio 导入工程
    Android 开发基础入门: android studio安装教程
    ESA2GJK1DH1K升级篇: 移植远程更新程序到STM32F103RET6型号的单片机,基于(GPRS模块AT指令TCP透传方式)
    【传输协议】http协议GET与POST传递数据的最大长度能够达到多少
  • 原文地址:https://www.cnblogs.com/Archger/p/8451601.html
Copyright © 2011-2022 走看看