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 ;
    }
    
    
  • 相关阅读:
    P1121 环状最大两段子段和
    无题
    cdoj 1485 柱爷搞子串 sam treap
    自然数幂和
    Gym 100341C AVL Trees NTT
    线性筛分解质因子
    codeforces 366 Ant Man dp
    UVALive 6914 Maze Mayhem 轮廓线dp
    hdu 5790 Prefix 字典树 主席树
    莫比乌斯反演个人小结
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12013363.html
Copyright © 2011-2022 走看看