bzoj 2120
先将问题转化为带修改的求区间小于某数的数的数量,然后用树状数组套值域线段树解决。
注意:
1、值域线段树要包括0
1 /************************************************************** 2 Problem: 2120 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:1556 ms 7 Memory:35512 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <set> 12 #define maxs 600000 13 #define maxn 10010 14 #define maxa 1000000 15 using namespace std; 16 17 struct Node { 18 int sz; 19 Node *ls, *rs; 20 }pool[maxs], *tail=pool, *root[maxn], *nds[maxn]; int ndc; 21 22 int n, m; 23 int aa[maxn], vv[maxa+1]; 24 int prv[maxn], nxt[maxn]; 25 set<int> st[maxa+1]; 26 27 Node *newnode() { 28 Node *nd = ++tail; 29 nd->sz = 0; 30 nd->ls = nd->rs = 0; 31 return nd; 32 } 33 void mdf_sgt( Node *nd, int lf, int rg, int pos, int delta ) { 34 if( lf==rg ) { 35 nd->sz += delta; 36 return; 37 } 38 int mid=(lf+rg)>>1; 39 if( pos<=mid ) { 40 if( !nd->ls ) nd->ls = newnode(); 41 mdf_sgt( nd->ls, lf, mid, pos, delta ); 42 } else { 43 if( !nd->rs ) nd->rs = newnode(); 44 mdf_sgt( nd->rs, mid+1, rg, pos, delta ); 45 } 46 nd->sz = 0; 47 if( nd->ls ) nd->sz+=nd->ls->sz; 48 if( nd->rs ) nd->sz+=nd->rs->sz; 49 } 50 int qry_sgt( int lf, int rg, int top ) { 51 if( lf==rg ) { 52 int rt=0; 53 for( int i=1; i<=ndc; i++ ) 54 if( nds[i] ) 55 rt += nds[i]->sz; 56 return rt; 57 } 58 int mid=(lf+rg)>>1; 59 if( top<=mid+1 ) { 60 for( int i=1; i<=ndc; i++ ) 61 if( nds[i] ) 62 nds[i] = nds[i]->ls; 63 return qry_sgt(lf,mid,top); 64 } else { 65 int rt = 0; 66 for( int i=1; i<=ndc; i++ ) 67 if( nds[i] ) { 68 if( nds[i]->ls ) 69 rt += nds[i]->ls->sz; 70 nds[i] = nds[i]->rs; 71 } 72 rt += qry_sgt(mid+1,rg,top); 73 return rt; 74 } 75 } 76 void init() { 77 for( int i=1; i<=n; i++ ) { 78 scanf( "%d", aa+i ); 79 if( vv[aa[i]] ) { 80 prv[i] = vv[aa[i]]; 81 nxt[prv[i]] = i; 82 } 83 vv[aa[i]] = i; 84 st[aa[i]].insert(i); 85 } 86 87 for( int i=1; i<=n; i++ ) 88 root[i] = newnode(); 89 for( int i=1; i<=n; i++ ) 90 for( int j=i; j<=n; j+=j&-j ) 91 mdf_sgt( root[j], 0, maxa, prv[i], +1 ); 92 } 93 void mdf_sub( int pos, int oldv, int newv ) { 94 for( int i=pos; i<=n; i+=i&-i ) 95 mdf_sgt( root[i], 0, maxa, oldv, -1 ); 96 for( int i=pos; i<=n; i+=i&-i ) 97 mdf_sgt( root[i], 0, maxa, newv, +1 ); 98 } 99 void modify( int pos, int val ) { 100 int a=prv[pos], b=nxt[pos]; 101 int p=0, q=0; 102 103 st[aa[pos]].erase(pos); 104 set<int>::iterator it = st[val].insert( pos ).first; 105 aa[pos] = val; 106 107 if( it!=st[val].begin() ) { 108 --it; 109 p = *it; 110 ++it; 111 } 112 ++it; 113 if( it!=st[val].end() ) 114 q = *it; 115 116 prv[pos] = p; 117 nxt[pos] = q; 118 if( b ) prv[b] = a; 119 if( a ) nxt[a] = b; 120 if( p ) nxt[p] = pos; 121 if( q ) prv[q] = pos; 122 mdf_sub( pos, a, p ); 123 if( b ) mdf_sub( b, pos, a ); 124 if( q ) mdf_sub( q, p, pos ); 125 } 126 int qry_sub( int R, int top ) { 127 ndc = 0; 128 for( int i=R; i; i-=i&-i ) 129 nds[++ndc]=root[i]; 130 int rt = qry_sgt(0,maxa,top); 131 return rt; 132 } 133 int query( int L, int R ) { 134 return qry_sub(R,L)-(L==1?0:qry_sub(L-1,L)); 135 } 136 int main() { 137 scanf( "%d%d", &n, &m ); 138 init(); 139 for( int i=1; i<=m; i++ ) { 140 char ch[10]; 141 scanf( "%s", ch ); 142 if( ch[0]=='R' ) { 143 int p, c; 144 scanf( "%d%d", &p, &c ); 145 modify( p, c ); 146 } else { 147 int l, r; 148 scanf( "%d%d", &l, &r ); 149 printf( "%d\n", query(l,r) ); 150 } 151 } 152 }