zoukankan      html  css  js  c++  java
  • HDU 6364 Ringland

    Ringland

    题意: 在一个环上有n个男生, n个女生, 现在要求每一个男生与女生配对, 求总代价最小。

    题解:

    如果2个男生到女生的路交叉了, 那么我们交换这2个男生的路, 总代价是一定会变得小的。

    所以组合方式是线性的.

    假设有3个男生 3个女生, 并且都已经排好序了。

    搭配方式一共有3种。

    1 <-> 1 2 <-> 2 3 <-> 3

    1 <-> 2 2 <-> 3 3 <-> 1

    1 <-> 3 2 <-> 1 3 <-> 2

    因为不想要路径交叉, 所以就按照顺序给他们排序配对。

    接下来就是顺时针走路和逆时针走的问题了。

    先将B 扩展成 3B 减少讨论。

    然后对于 a 来说 找到 a - 2/L 的位置 和 a + 1 的位置, 

    对 [a - 2/L,  a] 来说 贡献都是 a-b, 对 [a + 1, a + 2/ L] 贡献都是 b-a.

    然后对于每一个B也找到进入计算的时间, 出去的时间, 从负变成正的时间,然后搞一下差分就好了。

    代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
      4 #define LL long long
      5 #define ULL unsigned LL
      6 #define fi first
      7 #define se second
      8 #define pb push_back
      9 #define lson l,m,rt<<1
     10 #define rson m+1,r,rt<<1|1
     11 #define max3(a,b,c) max(a,max(b,c))
     12 #define min3(a,b,c) min(a,min(b,c))
     13 typedef pair<int,int> pll;
     14 const int inf = 0x3f3f3f3f;
     15 const LL INF = 0x3f3f3f3f3f3f3f3f;
     16 const LL mod =  (int)1e9+7;
     17 const int N = 2e6;
     18 LL a[N], b[N];
     19 int l[N], r[N], v[N], in[N], out[N];
     20 LL sum[N];
     21 struct FastIO {
     22     static const int S = 1310720;
     23     int wpos;
     24     char wbuf[S];
     25     FastIO() : wpos(0) { }
     26     inline int xchar() {
     27         static char buf[S];
     28         static int len = 0, pos = 0;
     29         if (pos == len) pos = 0, len = fread(buf, 1, S, stdin);
     30         if (pos == len) return -1;
     31         return buf[pos++];
     32     }
     33     inline int xint() {
     34         int c = xchar(), x = 0, s = 1;
     35         while (c <= 32) c = xchar();
     36         if (c == '-') s = -1, c = xchar();
     37         for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
     38         return x * s;
     39     }
     40     ~FastIO() {
     41         if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
     42     }
     43 } io;
     44 inline int Find(int x, LL v){
     45     while(b[x] < v) x++;
     46     return x;
     47 }
     48 LL n, L;
     49 void in1(){
     50     n = io.xint();
     51     L = io.xint();
     52     for(int i = 1; i <= n; i++){
     53         a[i] = io.xint();
     54         a[i] += L;
     55     }
     56     for(int i = 1; i <= n; i++)
     57         b[i] = io.xint();
     58 }
     59 void in2(){
     60     scanf("%lld%lld", &n, &L);
     61     for(int i = 1; i <= n; i++){
     62         scanf("%lld", &a[i]);
     63         a[i] += L;
     64     }
     65     for(int i = 1; i <= n; i++)
     66         scanf("%lld", &b[i]);
     67 }
     68 void solve(){
     69     in1();
     70     //in2();
     71     for(int i = 1;i <= 2*n; i++)
     72         b[i+n] = b[i] + L;
     73     for(int i = 1; i <= n; i++){
     74         l[i] = Find(l[i-1], a[i] - L/2);
     75         r[i] = Find(r[i-1], a[i] + 1);
     76     }
     77     int lf = l[1];
     78     memset(sum, 0, sizeof(LL) *(n+1));
     79     for(int i = 1; i <= n; i++) sum[1] += a[i];
     80     for(int i = 1; i <= n; i++){
     81         int t = r[i] - lf + 1;
     82         if(t - i >= 0) sum[t-i+1] -= 2 * a[i];
     83         else sum[1] -= a[i];
     84     }
     85     v[0] = 1;
     86     out[0] = 1;
     87     int j = 1;
     88     for(int i = lf; i <= n*3; i++, j++){
     89         if(j <= n) in[j] = 1;
     90         else in[j] = in[j-1] + 1;
     91         out[j] = out[j-1] + 1;
     92         v[j] = v[j-1];
     93         while(v[j] <= n && a[v[j]] < b[i]) v[j]++;
     94         if(in[j] > n) break;
     95     }
     96     for(int i = 1; i < j; i++){
     97         if(i <= n){
     98             v[i] = i - (v[i]-1) + 1;
     99             if(v[i] < 1) v[i] = 1;
    100         }
    101         else {
    102             if(v[i] == n+1) v[i] = in[i];
    103             else v[i] = in[i] + (n - v[i] + 1);
    104         }
    105     }
    106     for(int i = 1, p = lf; i < j; i++, p++){
    107         sum[in[i]] -= b[p];
    108         if(out[i] <= v[i]) sum[out[i]] += b[p];
    109         else {
    110             sum[v[i]] += 2 * b[p];
    111             sum[out[i]] -= b[p];
    112         }
    113     }
    114     LL ans = INF, tmp = 0;;
    115     for(int i = 1; i <= n; i++){
    116         tmp += sum[i];
    117         ans = min(ans, tmp);
    118     }
    119     printf("%lld
    ", ans);
    120 }
    121 int main(){
    122     int t;
    123     scanf("%d", &t);
    124     while(t--){
    125         solve();
    126     }
    127     return 0;
    128 }
    View Code
  • 相关阅读:
    WisDom .net开发框架设计 2
    多线程处理大数组
    C#核心语法
    怎样控制与复制相同的功能
    SQL 内存数据库的细节
    验证编辑方法(Edit method)和编辑视图(Edit view)
    上传图片检测其是否为真实的图片 防范病毒上传至服务器
    chrome切换hosts插件 hostsadmin
    程序托盘图标+右键弹出菜单
    30多年程序员生涯经验总结(成功源自于失败中的学习;失败则是因为容忍错误的横行)
  • 原文地址:https://www.cnblogs.com/MingSD/p/9458663.html
Copyright © 2011-2022 走看看