zoukankan      html  css  js  c++  java
  • hdu5481 Desiderium

    1. 链接


       Desiderium
    2. 题意

        给定n条线段,从中选取若干条,共有2n种选法(因为每一条线段有两种方法:选或者不选).

        每一种选法都对应一个长度,也就是所选线段的并集长度.

        求这2n种选法长度之和.

    3. 解法:

      把这n条线段进行离散化,使得任意一条线段都可以由若干条元线段组成.

      什么叫元线段呢?把全部的x坐标进行排序,去重,就得到了很多元线段.

      统计每条元线段出现的次数,也就是说它被这n条线段里面的多少个线段覆盖.

      如合统计呢?假设元线段被m条线段覆盖,那么有n-m条线段不覆盖它.

      所以,该元线段被2n种选法中的2n-2n-m种选法覆盖.

      ans=累加(元线段的长度*元线段使用的次数).

    4. 写法:

      主要是如何统计元线段出现的次数.

      • 建立线段树,把没一条线段进行插入O(nlgn)
      • 树状数组O(nlgn)
      • 普通数组O(n),这种方法最好,不仅简单,而且快.
    5. 代码(树状数组版):

      #include<iostream>
      #include<string.h>
      #include<stdio.h>
      #include<math.h>
      #include<stdlib.h>
      #include<algorithm>
      using namespace std;
      #define re(i,n) for(int i=0;i<n;i++)
      typedef long long ll;
      const int maxn = 1e5 + 7;
      const int mod = 1e9 + 7;
      int n;
      struct Re{
      	int l, r;
      }a[maxn];
      int x[maxn << 1], xi;
      int tr[maxn << 1];
      #define lson(x) x<<1,f,mid
      #define rson(x) x<<1|1,mid+1,r
      int lowbit(int x){
      	return x&-x;
      }
      void ins(int x, int v){
      	for (int i = x; i > 0; i -= lowbit(i)){
      		tr[i] += v;
      	}
      }
      int query(int x){
      	int ans = 0;
      	for (int i = x; i < xi; i += lowbit(i)){
      		ans += tr[i];
      	}
      	return ans;
      }
      int data[maxn];
      int f(int m){
      	return data[n] - data[n - m];
      }
      void init(){
      	data[0] = 1;
      	re(i, maxn - 2){
      		data[i + 1] = ((ll)data[i] << 1) % mod;
      	}
      }
      int cnt[maxn << 1];
      int main(){
      	//freopen("in.txt", "r", stdin); 
      	init();
      	int T; cin >> T;
      	while (T--){
      		scanf("%d", &n);
      		xi = -1;
      		re(i, n){
      			scanf("%d%d", &a[i].l, &a[i].r);
      			x[++xi] = a[i].l, x[++xi] = a[i].r;
      		}
      		++xi;
      		sort(x, x + xi);
      		xi = unique(x, x + xi) - x;
      		memset(tr, 0, sizeof(tr));
      		re(i, n){
      			int beg = lower_bound(x, x + xi, a[i].l) - x;
      			int over = lower_bound(x, x + xi, a[i].r) - x;
      			ins(beg, -1), ins(over, 1);
      		}
      		cnt[0] = 0;
      		for (int i = 1; i < xi; i++)cnt[i] = query(i);
      		//re(i, xi)printf("(%d,%d) ", i, cnt[i]);
      		//puts("");
      		ll ans = 0;
      		re(i, xi - 1){
      			ll len = (ll)x[i + 1] - x[i];
      			int ge = cnt[i + 1];
      			//cout << len << " " << ge << endl;
      			ans = (len*f(ge) + ans) % mod;
      		}
      		if (ans < 0)ans += mod;
      		printf("%lld
      ", ans);
      	}
      	return 0;
      }
      
    6.  代码(普通数组版):

       1 #include<iostream>
       2 #include<algorithm>
       3 #include<stdio.h>
       4 using namespace std;
       5 typedef long long ll;
       6 #define re(i,n) for(int i=0;i<n;i++)
       7 const int maxn = 1e5 + 7;
       8 const int mod = 1e9 + 7;
       9 struct Node{
      10     int l, r;
      11 }a[maxn];
      12 int n;
      13 int x[maxn << 1], xi;
      14 int cnt[maxn << 1];
      15 int data[maxn];
      16 void init(){
      17     data[0] = 1;
      18     for (int i = 1; i < maxn-3; i++){
      19         data[i] = (data[i - 1] << 1) % mod;
      20     }
      21 }
      22 int main(){
      23     //freopen("in.txt", "r", stdin);
      24     int T; cin >> T;
      25     init();
      26     while (T--){
      27         scanf("%d", &n);
      28         xi = -1;
      29         re(i, n)scanf("%d%d", &a[i].l, &a[i].r), x[++xi] = a[i].l, x[++xi] = a[i].r;
      30         sort(x, x + xi + 1);
      31         xi = unique(x, x + xi + 1) - x;
      32         re(i, xi)cnt[i] = 0;
      33         re(i, n){ 
      34             int f = lower_bound(x, x + xi, a[i].l) - x,
      35                 t = lower_bound(x, x + xi, a[i].r) - x;
      36             cnt[t]++, cnt[f]--;
      37         }
      38         for (int i = xi - 2; i >= 0; i--){
      39             cnt[i] += cnt[i + 1];
      40         }
      41         ll ans = 0;
      42         re(i, xi-1){
      43             int len = x[i + 1] - x[i];
      44             int m= cnt[i + 1];
      45             ans = (ans + (ll)len*(data[n] - data[n - m])) % mod;
      46         }
      47         if (ans < 0)ans += mod;
      48         printf("%lld
      ", ans);
      49     }
      50     return 0;
      51 }
  • 相关阅读:
    使用IIS实现反向代理
    C#管理windows服务
    使用SoapUI测试windows身份验证的webservice
    SQLSERVER2014集群实战——IP引发的坑
    (复活公告??)
    各种trick和细节错误汇总
    emacs常用指令
    随机数据生成与对拍【c++版,良心讲解】
    UVA11019 Matrix Matcher
    HDU4757 Tree
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/4844391.html
Copyright © 2011-2022 走看看