zoukankan      html  css  js  c++  java
  • 整体二分的一些见解[整体二分学习笔记]

    整体二分大概就是这么一种算法

    • 基本上和树状数组一起用
    • 离线
    • 二分

    好进入正文

    先给个题呗

    这题给出多个询问 而你每次询问的复杂度是 (O(n log n)) 看似很优秀了?
    但你这样的话 所有的复杂度都是 (O(n log n)) 整体复杂度乘个 (Q) 接受不了…

    二分怎么写?

    while(l <= r) {
        int mid = l + r >> 1 ;
        if(chk(mid)) { ans = mid ; l = mid + 1 ; }
        else r = mid - 1 ;
    }
    

    大概是这样 反过来的不说了…

    然后每次边做 边丢队列里…
    存俩队列 q1 , q2

    满足 条件的放 q2 减掉左区间的贡献
    不满足的放 q1 不做修改
    易证明 q1.size + q2.size = q.size
    然后抵消贡献 这个贡献有时候可以用-1 +1 来处理掉(即存两个)

    所以归位 然后接着分治 如果说 L==R 了 就和二分一个样子 赋上 ans = L 跑路

    // Isaunoya
    #include<bits/stdc++.h>
    using namespace std ;
    using LL = long long ;
    using uint = unsigned int ;
    #define int long long
    #define fir first
    #define sec second
    #define pb push_back
    #define mp(x , y) make_pair(x , y)
    template < typename T > inline void read(T & x) { x = 0 ; int f = 1 ; register char c = getchar() ;
      for( ; ! isdigit(c) ; c = getchar()) if(c == '-') f = -1 ;
      for( ; isdigit(c) ; c = getchar()) x = (x << 1) + (x << 3) + (c & 15) ;
      x *= f ;
    }
    template < typename T > inline void print(T x) {
      if(! x) { putchar('0') ; return ; } static int st[105] ;
      if(x < 0) putchar('-') , x = -x ; int tp = 0 ;
      while(x) st[++ tp] = x % 10 , x /= 10 ; while(tp) putchar(st[tp --] + '0') ;
    }
    template < typename T > inline void print(T x , char c) { print(x) ; putchar(c) ; }
    template < typename T , typename ...Args > inline void read(T & x , Args & ...args) { read(x) ; read(args...) ; }
    template < typename T > inline void sort( vector < T > & v) { sort(v.begin() , v.end()) ; return ; }
    template < typename T > inline void unique( vector < T > & v) { sort(v) ; v.erase(unique(v.begin() , v.end()) , v.end()) ; }
    template < typename T > inline void cmax(T & x , T y) { if(x < y) x = y ; return ; }
    template < typename T > inline void cmin(T & x , T y) { if(x > y) x = y ; return ; }
    int n , m , k ;
    const int N = 3e5 + 10 ;
    struct node { int v , nxt ; } e[N] ;
    struct Node { int ned , id , hd ; } q[N] , _q[N << 1] ;
    int head[N] , cnt = 0 ;
    int L[N] , R[N] , val[N] ;
    inline void addedge(int u , int v) { e[++ cnt].v = v ; e[cnt].nxt = q[u].hd ; q[u].hd = cnt ; }
    int c[N << 1] ;
    inline int low(int x) { return x & -x ; }
    inline void add(int x , int y) { for( ; x <= N << 1 ; x +=low(x)) c[x] += y ; }
    inline int query(int x) { int ans = 0 ; for( ; x ; x ^= low(x)) ans += c[x] ; return ans ; }
    int ans[N] ;
    inline void solve(int l , int r , int x , int y) {
      if(l == r) { for(register int i = x ; i <= y ; i ++) ans[q[i].id] = l ; return ; }
      int mid = l + r >> 1 ; int ql = 0 , qr = n ;
      for(register int i = l ; i <= mid ; i ++) add(L[i] , val[i]) , add(R[i] + 1 , - val[i]) ;
      for(register int i = x ; i <= y ; i ++) {
        int tmp = 0 ;
        for(register int j = q[i].hd ; j && tmp <= q[i].ned ; j = e[j].nxt) {
          int v = e[j].v ;
          tmp += query(v + m) + query(v) ;
        }
        if(tmp >= q[i].ned) _q[++ ql] = q[i] ;
        else { _q[++ qr] = q[i] ; _q[qr].ned -= tmp ; }
      }
      for(register int i = l ; i <= mid ; i ++) add(L[i] , - val[i]) , add(R[i] + 1 , val[i]) ;
      for(register int i = 1 ; i <= ql ; i ++) q[x + i - 1] = _q[i] ;
      for(register int i = n + 1 ; i <= qr ; i ++) q[x + ql + i - n - 1] = _q[i] ;
      solve(l , mid , x , x + ql - 1) ;
      solve(mid + 1 , r , y - qr + n + 1 , y) ;
    }
    
    signed main() {
      read(n , m) ; for(register int i = 1 ; i <= m ; i ++) { int x ; read(x) ; addedge(x , i) ; }
      for(register int i = 1 ; i <= n ; i ++) read(q[i].ned) , q[i].id = i ;
      read(k) ; for(register int i = 1 ; i <= k ; i ++) read(L[i] , R[i] , val[i]) ;
      for(register int i = 1 ; i <= k ; i ++) if(L[i] > R[i]) R[i] += m ; solve(1 , k + 1 , 1 , n) ;
      for(register int i = 1 ; i <= n ; i ++)
        if(ans[i] == k + 1) puts("NIE") ;
        else printf("%lld
    " , ans[i]) ;
      return 0 ;
    }
    
    
  • 相关阅读:
    Introduction to debugging neural networks
    Faster R-CNN教程
    最长递增子序列
    321. Create Maximum Number 解题方法详解
    Ubuntu安装opencv with cuda
    转载:LeetCode:5Longest Palindromic Substring 最长回文子串
    64. Minimum Path Sum
    322. Coin Change
    148. Sort List
    微信浏览器禁止页面下拉查看网址(不影响页面内部scroll)
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12013363.html
Copyright © 2011-2022 走看看