码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 3110

时间:2015-04-28 22:45:38      阅读:243      评论:0      收藏:0      [点我收藏+]

标签:

 
整体二分。
首先,第k大问题是满足二分性的(只要我们能够快速求出集合中比某个数小的数的个数,那么就可以快速找出该集合的第K大)。
然后考虑整体二分,关键是我们怎么将询问分到其对应的答案子区间中。
和普通的区间第K大的做法一样,我们先将修改按照大小排序(普通的区间第K大就是给出的原序列,而这里就是区间修改)。
设对于答案区间[lf,rg],有询问集合q,求出当前区间的mid,然后二分外面的修改数组,找出大小在[lf,mid]中的所有修改,将它们提出来,按照修改的顺序排序,然后和询问一起沿时间轴扫过去,过程中维护一个线段树,其以位置为下表,表示从最开始到现在每个位置中的数比mid小的数的个数。遇到修改就将对应的区间每个位置+1(区间修改),遇到询问就查询其对应区间的和(区间求和),根据其区间中小于等于mid的数的个数判断答案是与mid的关系,从而确定它的答案子区间。
 
时间复杂度:O( m * logn * logn )(改天把树套树的做法补上)。
 
技术分享
  1 /**************************************************************
  2     Problem: 3110
  3     User: idy002
  4     Language: C++
  5     Result: Accepted
  6     Time:5584 ms
  7     Memory:6432 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <vector>
 12 #include <algorithm>
 13 #define N 50010
 14 using namespace std;
 15  
 16 struct Query {
 17     int id, l, r, k;
 18     int ans;
 19     Query(){}
 20     Query( int id, int l, int r, int k ):id(id),l(l),r(r),k(k){}
 21 };
 22 struct Modify {
 23     int id, l, r, k;
 24     Modify(){}
 25     Modify( int id, int l, int r, int k ):id(id),l(l),r(r),k(k){}
 26     bool operator<( const Modify &o ) const {
 27         return k<o.k;
 28     }
 29 };
 30 bool operator<( const Modify &o, int k ) { return o.k<k; }
 31 bool operator<( int k, const Modify &o ) { return k<o.k; }
 32 struct Node {
 33     int s, tag;
 34     Node *ls, *rs;
 35 }pool[3*N], *tail=pool, *root;
 36  
 37 int n, m, maxk;
 38 int disc[N], dtot;
 39 int ans[N];
 40 Query qry[N]; int tq;
 41 Modify mdf[N]; int tm;
 42  
 43 inline void update( Node *nd ) {
 44     nd->s = nd->ls->s + nd->rs->s;
 45 }
 46 Node *build( int lf, int rg ) {
 47     Node *nd = ++tail;
 48     if( lf==rg ) return nd;
 49     int mid=(lf+rg)>>1;
 50     nd->ls = build( lf, mid );
 51     nd->rs = build( mid+1, rg );
 52     return nd;
 53 }
 54 void pushdown( Node *nd, int lf, int rg ) {
 55     if( nd->tag ) {
 56         int mid=(lf+rg)>>1;
 57         nd->ls->s += (mid-lf+1)*nd->tag;
 58         nd->rs->s += (rg-mid)*nd->tag;
 59         nd->ls->tag += nd->tag;
 60         nd->rs->tag += nd->tag;
 61         nd->tag = 0;
 62     }
 63 }
 64 void modify( Node *nd, int lf, int rg, int L, int R, int delta ) {
 65     if( L<=lf && rg<=R ) {
 66         nd->s += (rg-lf+1)*delta;
 67         nd->tag += delta;
 68         return;
 69     }
 70     pushdown(nd,lf,rg);
 71     int mid=(lf+rg)>>1;
 72     if( L<=mid ) modify( nd->ls, lf, mid, L, R, delta );
 73     if( R>mid ) modify( nd->rs, mid+1, rg, L, R, delta );
 74     update( nd );
 75 }
 76 int query( Node *nd, int lf, int rg, int L, int R ) {
 77     if( L<=lf && rg<=R ) return nd->s;
 78     pushdown(nd,lf,rg);
 79     int mid=(lf+rg)>>1;
 80     int rt = 0;
 81     if( L<=mid ) rt+=query( nd->ls, lf, mid, L, R );
 82     if( R>mid ) rt+=query( nd->rs, mid+1, rg, L, R );
 83     update(nd);
 84     return rt;
 85 }
 86 bool cmp_id( int a, int b ) {
 87     return mdf[a].id<mdf[b].id;
 88 }
 89 void binary( int lf, int rg, vector<int> vq ) {
 90     if( vq.empty() ) return;
 91     if( lf==rg ) {
 92         for( int t=0; t<vq.size(); t++ ) 
 93             qry[vq[t]].ans = -disc[lf];
 94         return;
 95     }
 96     int mid=(lf+rg)>>1;
 97     int lpos = lower_bound( mdf+1, mdf+1+tm, lf ) - mdf;
 98     int rpos = upper_bound( mdf+1, mdf+1+tm, mid ) - mdf - 1;
 99     vector<int> vm;
100     for( int i=lpos; i<=rpos; i++ )
101         vm.push_back(i);
102     sort( vm.begin(), vm.end(), cmp_id );
103  
104     int i, j;
105     vector<int> ql, qr;
106     for( i=0,j=-1; i<vq.size(); i++ ) {
107         while( j+1<vm.size() && mdf[vm[j+1]].id<qry[vq[i]].id ) {
108             j++;
109             modify( root, 1, n, mdf[vm[j]].l, mdf[vm[j]].r, +1 );
110 //          fprintf( stderr, "modify( %d %d %d )\n", mdf[vm[j]].l, mdf[vm[j]].r,
111 //                  +1 );
112         }
113         int c = query( root, 1, n, qry[vq[i]].l, qry[vq[i]].r );
114 //      fprintf( stderr, "query( %d %d ) = %d\n", qry[vq[i]].l, qry[vq[i]].r, c );
115         if( qry[vq[i]].k<=c )
116             ql.push_back( vq[i] );
117         else {
118             qr.push_back( vq[i] );
119             qry[vq[i]].k -= c;
120         }
121     }
122     for( int k=0; k<=j; k++ ) {
123         modify( root, 1, n, mdf[vm[k]].l, mdf[vm[k]].r, -1 );
124 //      fprintf( stderr, "modify( %d %d %d )\n", mdf[vm[k]].l, mdf[vm[k]].r, -1 );
125     }
126     binary( lf, mid, ql );
127     binary( mid+1, rg, qr );
128 }
129 int main() {
130     scanf( "%d%d", &n, &m );
131     for( int i=1,o,l,r,k; i<=m; i++ ) {
132         scanf( "%d%d%d%d", &o, &l, &r, &k );
133         if( o==2 ) {
134             qry[++tq] = Query(i,l,r,k);
135             maxk = max( maxk, k );
136         } else {
137             k = -k;
138             mdf[++tm] = Modify(i,l,r,k);
139             disc[++dtot] = k;
140         }
141     }
142     sort( disc+1, disc+1+dtot );
143     dtot = unique( disc+1, disc+1+dtot ) - disc - 1;
144  
145     sort( mdf+1, mdf+1+tm );
146     for( int i=1; i<=tm; i++ )
147         mdf[i].k = lower_bound( disc+1, disc+1+dtot, mdf[i].k ) - disc;
148  
149     vector<int> vq;
150     for( int i=1; i<=tq; i++ ) 
151         vq.push_back(i);
152      
153     root = build( 1, n );
154     binary( 1, dtot, vq );
155     for( int i=1; i<=tq; i++ )
156         printf( "%d\n", qry[i].ans );
157 }
View Code

 

 

bzoj 3110

标签:

原文地址:http://www.cnblogs.com/idy002/p/4464096.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!