zoukankan      html  css  js  c++  java
  • 线段树 单点更新,区间查询

    hdu2795 Billboard

     1 #include<iostream>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cstdio>
     5 #include<string>
     6 #include<queue>
     7 #include<cmath>
     8 #include<vector>
     9 
    10 using namespace std;
    11 
    12 #define mnx 204000
    13 #define ll long long
    14 #define inf 0x3f3f3f3f
    15 #define lson l, m, rt << 1
    16 #define rson m+1, r, rt << 1 | 1
    17 
    18 int sum[mnx<<2], h, w, n;;
    19 void pushup( int rt ){
    20     sum[rt] = max( sum[rt<<1], sum[rt<<1|1] );
    21 }
    22 void build( int l, int r, int rt ){
    23     if( l == r ){
    24         sum[rt] = w; return ;
    25     }
    26     int m = ( l + r ) >> 1;
    27     build( lson );
    28     build( rson );
    29     pushup( rt );
    30 }
    31 int find( int v, int l, int r, int rt ){
    32     int ret;
    33     if( l == r ){
    34         if( sum[rt] < v ) ret = -1;
    35         else sum[rt] -= v, ret = l;
    36         return ret;
    37     }
    38     int m = ( l + r ) >> 1;
    39     if( sum[rt<<1] >= v ){
    40         ret = find( v, lson );
    41     }
    42     else  ret = find( v, rson );
    43     pushup( rt );
    44     return ret;
    45 }
    46 int main(){
    47     while( scanf( "%d %d %d", &h, &w, &n ) != EOF ){
    48         h = min( h, n );
    49         build( 1, h, 1 );
    50         int ww;
    51         for( int i = 0; i < n; i++ ){
    52             scanf( "%d", &ww );
    53             printf( "%d
    ", find( ww, 1, h, 1 ) );
    54         }
    55     }
    56     return 0;
    57 }
    View Code

    poj2828 Buy Tickets

    思路:倒序插入,这样POS的意义就变为找到这么一个位置可以放置这个人, 使得从这个位置往前数共有POS个空位,线段树的节点中cnt表示在[l,r)区间中共有多少 个空位

     1 #include<iostream>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cstdio>
     5 #include<string>
     6 #include<queue>
     7 #include<cmath>
     8 #include<vector>
     9 
    10 using namespace std;
    11 
    12 #define mnx 204000
    13 #define ll long long
    14 #define inf 0x3f3f3f3f
    15 #define lson l, m, rt << 1
    16 #define rson m+1, r, rt << 1 | 1
    17 
    18 int sum[mnx<<2], pos[mnx], val[mnx], ans[mnx], n;
    19 void pushup( int rt ){
    20     sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    21 }
    22 void build( int l, int r, int rt ){
    23     if( l == r ){
    24         sum[rt] = 1; return ;
    25     }
    26     int m = ( l + r ) >> 1;
    27     build( lson );
    28     build( rson );
    29     pushup( rt );
    30 }
    31 void update( int p, int v, int l, int r, int rt ){
    32     if( l == r ){
    33         sum[rt] = 0;
    34         ans[l] = v;
    35         return ;
    36     }
    37     int m = ( l + r ) >> 1;
    38     if( p <= sum[rt<<1] ) update( p, v, lson );
    39     else update( p - sum[rt<<1], v, rson );
    40     pushup( rt );
    41 }
    42 int main(){
    43     while( scanf( "%d", &n ) != EOF ){
    44         for( int i = 0; i < n; i++ ){
    45             scanf( "%d %d", &pos[i], &val[i] );
    46         }
    47         build( 1, n, 1 );
    48         for( int i = n - 1; i >= 0; i-- ){
    49             update( pos[i]+1, val[i], 1, n, 1 );
    50         }
    51         for( int i = 1; i <= n; i++ ){
    52             printf( "%d%c", ans[i], i == n ? '
    ' : ' ' );
    53         }
    54     }
    55     return 0;
    56 }
    View Code

    poj2886 Who Gets the Most Candies?

    思路:线段数 反素数(反素数不懂的去问度娘,看博客)。。 先算出N个人中,是第几个人(ans)跳出来得到的糖果最多(用dfs算出)。然后模拟ans遍。。
    线段树的结点中保存该区间内还剩多少人,每次update 删除一个人。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cstdio>
     5 #include<string>
     6 #include<queue>
     7 #include<cmath>
     8 #include<vector>
     9 
    10 using namespace std;
    11 
    12 #define mnx 504000
    13 #define ll long long
    14 #define inf 0x3f3f3f3f
    15 #define lson l, m, rt << 1
    16 #define rson m+1, r, rt << 1 | 1
    17 
    18 int sum[mnx<<2], n, val[mnx], cnt, best, ans;
    19 char ch[mnx][11];
    20 int p[16] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
    21 void pushup( int rt ){
    22     sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    23 }
    24 void build( int l, int r, int rt ){
    25     if( l == r ){
    26         sum[rt] = 1;
    27         return ;
    28     }
    29     int m = ( l + r ) >> 1;
    30     build( lson );
    31     build( rson );
    32     pushup( rt );
    33 }
    34 int update( int p, int l, int r, int rt ){
    35     int ret;
    36     if( l == r ){
    37         sum[rt] = 0;
    38         return l;
    39     }
    40     int m = ( l + r ) >> 1;
    41     if( sum[rt<<1] >= p ) ret = update( p, lson );
    42     else ret = update( p - sum[rt<<1], rson );
    43     pushup( rt );
    44     return ret;
    45 }
    46 void dfs( int dept, int tmp, int num ){
    47     if( dept >= 16 ) return;
    48     if( num > best ){
    49         best = num;
    50         ans = tmp;
    51     }
    52     if( num == best && ans > tmp ) ans = tmp;
    53     for( int i = 1; i <= 20; i++ ){
    54         if( n / p[dept] < tmp ) break;
    55         dfs( dept + 1, tmp *= p[dept], num * ( i + 1 ) );
    56     }
    57 }
    58 int main(){
    59     int k;
    60     while( scanf( "%d %d", &n, &k ) != EOF ){
    61         ans = inf;
    62         best = 0;
    63         dfs( 0, 1, 1 );
    64         build( 1, n, 1 );
    65         cnt = 1;
    66         for( int i = 1; i <= n; i++ ){
    67             scanf( "%s %d", &ch[i], &val[i] );
    68         }
    69         int mod, pre;
    70         for( int i = 0; i < ans; i++ ){
    71             pre = k;
    72             k = update( k, 1, n, 1 );
    73             if( i == ans-1 ) break;
    74             mod = sum[1];
    75             if( val[k] > 0 ){
    76                 k = ( pre - 1 + val[k] % mod ) % mod;
    77                 if( k == 0 ) k = mod;
    78             }
    79             else{
    80                 k = ( mod + pre - ( -val[k] % mod ) ) % mod ;
    81                 if( k == 0 ) k = mod;
    82             } 
    83         }
    84         printf( "%s %d
    ", ch[k], best );
    85     }
    86     return 0;
    87 }
    View Code

    http://poj.org/problem?id=3264 Balanced Lineup

    线段树作用,区间查询。。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<string>
     5 #include<queue>
     6 #include<cmath>
     7 #include<vector>
     8 
     9 using namespace std;
    10 
    11 #define mnx 50005
    12 #define ll long long
    13 #define mod 1000000007
    14 #define inf 0x3f3f3f3f
    15 #define lson l, m, rt << 1
    16 #define rson m+1, r, rt << 1 | 1
    17 
    18 int max( int a, int b ){
    19     return a > b ? a : b;
    20 }
    21 int min( int a, int b ){
    22     return a < b ? a : b;
    23 }
    24 int max_rt[mnx<<2], min_rt[mnx<<2], ans1, ans2;
    25 void build( int l, int r, int rt ){
    26     if( l == r ){
    27         scanf( "%d", &max_rt[rt] );
    28         min_rt[rt] = max_rt[rt];
    29         return ;
    30     }
    31     int m = ( l + r ) >> 1;
    32     build( lson ); build( rson );
    33     max_rt[rt] = max( max_rt[rt<<1], max_rt[rt<<1|1] );
    34     min_rt[rt] = min( min_rt[rt<<1], min_rt[rt<<1|1] );
    35 }
    36 void find( int L, int R, int l, int r, int rt ){
    37     if( L <= l && R >= r ){
    38         ans1 = max( ans1, max_rt[rt] );
    39         ans2 = min( ans2, min_rt[rt] );
    40         return ;
    41     }
    42     int m = ( l + r ) >> 1;
    43     if( L <= m ) find( L, R, lson );
    44     if( R > m ) find( L, R, rson );
    45 }
    46 int main(){
    47     int n, q;
    48     while( scanf( "%d %d", &n, &q ) != EOF ){
    49         build( 1, n, 1 );
    50         while( q-- ){
    51             int l, r;
    52             ans1 = 0, ans2 = inf;
    53             scanf( "%d %d", &l, &r);
    54             find( l, r, 1, n, 1 );
    55             printf( "%d
    ", ans1 - ans2 );
    56         }
    57     }
    58     return 0;
    59 }
    View Code

    ZOJ 3772 Calculate the Function

    思路:首先,对于形如f(x) = p * f(x-1) + q * f(x-2)的通项都可以转成矩阵乘法。。

    f(x)=f(x-1) + a[x]* f(x-2), 所以就有递推式

    所以当r>=l+1时,

    然后就可以先求出:

    用线段树就可以在O(logn)的时间求出这个式子,不过线段树的每个节点保存的是一个矩阵

    还有就是要注意矩阵乘的方向

    总的复杂度是O(nlogn+mlogn),线段树作用 区间查询

     1 #include<iostream>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cstdio>
     5 #include<string>
     6 #include<queue>
     7 #include<cmath>
     8 #include<vector>
     9 
    10 using namespace std;
    11 
    12 #define mnx 104000
    13 #define ll long long
    14 #define mod 1000000007
    15 #define inf 0x3f3f3f3f
    16 #define lson l, m, rt << 1
    17 #define rson m+1, r, rt << 1 | 1
    18 
    19 ll b[mnx];
    20 struct mat{
    21     ll a[2][2];
    22     mat(){
    23         memset( a, 0, sizeof(a) );
    24     }
    25     mat( ll x ){
    26         a[0][0] = 1, a[1][0] = 1;
    27         a[0][1] = x, a[1][1] = 0;
    28     }
    29     mat operator * ( const mat & b ) const{
    30         mat ret;
    31         for( int i = 0; i < 2; i++ )
    32             for( int j = 0; j < 2; j++ )
    33                 for( int k = 0; k < 2; k++ )
    34                     ret.a[i][j] = ( ret.a[i][j] + a[i][k] * b.a[k][j] ) % mod;
    35         return ret;
    36     }
    37 }sum[mnx<<2];
    38 void build( int l, int r, int rt ){
    39     if( l == r ){
    40         sum[rt] = mat( b[l] );
    41         return ;
    42     }
    43     int m = ( l + r ) >> 1;
    44     build( lson );
    45     build( rson );
    46     sum[rt] = sum[rt<<1|1] * sum[rt<<1];
    47 }
    48 mat find( int L, int R, int l, int r, int rt ){
    49     mat ret;
    50     ret.a[0][0] = ret.a[1][1] = 1, ret.a[1][0] = ret.a[0][1] = 0;
    51     if( L <= l && R >= r ){
    52         return sum[rt];
    53     }
    54     int m = ( l + r ) >> 1;
    55     if( R > m ) ret = ret * find( L, R, rson );
    56     if( L <= m ) ret = ret * find( L, R, lson );
    57     return ret;
    58 }
    59 int main(){
    60     int cas;
    61     scanf( "%d", &cas );
    62     while( cas-- ){
    63         int n, m;
    64         scanf( "%d %d", &n, &m );
    65         for( int i = 1; i <= n; i++ ){
    66             scanf( "%lld", &b[i] );
    67         }
    68         build( 1, n, 1 );
    69         while( m-- ){
    70             int l, r;
    71             scanf( "%d %d", &l, &r );
    72             if( l == r || l + 1 == r ){
    73                 printf( "%lld
    ", b[r] );
    74             }
    75             else{
    76                 mat ans = find( l + 2, r, 1, n, 1 ), q;
    77                 q.a[0][0] = b[l+1], q.a[1][0] = b[l], q.a[0][1] = q.a[1][1] = 0;
    78                 ans = ans * q;
    79                 printf( "%lld
    ", ans.a[0][0] );
    80             }
    81         }
    82     }
    83     return 0;
    84 }
    View Code

    hdu4027 Can you answer these queries?

    看起来好像要区间更新,但实际上是单点更新。。每个叶子节点进行开根号,进行几次开方之后就变成了1,以后就不用在开方了。。用一个vis[]数组对每个节点进行标记,如果vis[] = true,就说明该区间的所有节点都是1,就不用进行开根号。。叶子节点是1的话,vis[rt] = true;其他节点就看左右儿子,if( vis[rt<<1] && vis[rt<<1|1] ) vis[rt] = true;

    这道题还有一个特别坑爹的地方:就是输入的要操作的区间,x不一定小于y,所以如果x>y的话,就要swap( x, y );

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<string>
     6 #include<cmath>
     7 #include<map>
     8 #include<queue>
     9 
    10 using namespace std;
    11 
    12 #define mnx 200005
    13 #define Pi acos(-1.0)
    14 #define ull unsigned long long
    15 #define ll long long 
    16 #define inf 0x3f3f3f3f
    17 #define eps 1e-8
    18 #define MP make_pair
    19 #define lson l, m, rt << 1
    20 #define rson m+1, r, rt << 1 | 1
    21 #define mod 2333333
    22 
    23 ll sum[mnx<<2];
    24 bool vis[mnx<<2];
    25 void pushup( int rt ){
    26     sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    27     if( vis[rt<<1] && vis[rt<<1|1] ) vis[rt] = 1;
    28 }
    29 void build( int l, int r, int rt ){
    30     if( l == r ){
    31         scanf( "%I64d", &sum[rt] );
    32         if( sum[rt] == 1 ) vis[rt] = 1;
    33         return ;
    34     }
    35     int m = ( l + r ) >> 1;
    36     build( lson );
    37     build( rson );
    38     pushup( rt );
    39 }
    40 ll query( int L, int R, int l, int r, int rt ){
    41     if( L <= l && R >= r ){
    42         return sum[rt];
    43     }
    44     ll ret = 0, m = ( l + r ) >> 1;
    45     if( L <= m ) ret += query( L, R, lson );
    46     if( R > m ) ret += query( L, R, rson );
    47     return ret;
    48 }
    49 void update( int L, int R, int l, int r, int rt ){
    50     if( vis[rt] ) return;
    51     if( l == r && L <= l && R >= r ){
    52         sum[rt] = sqrt( sum[rt] - 0.0 );
    53         if( sum[rt] == 1 ) vis[rt] = 1;
    54         return ;
    55     }
    56     int m = ( l + r ) >> 1;
    57     if( L <= m ) update( L, R, lson );
    58     if( R > m ) update( L, R, rson );
    59     pushup( rt );
    60 }
    61 int main(){
    62     int n, m, cnt = 1, op;
    63     while( scanf( "%d", &n ) != EOF ){
    64         memset( vis, 0, sizeof(vis) );
    65         build( 1, n, 1 );
    66         scanf( "%d", &m );
    67         printf( "Case #%d:
    ", cnt++ );
    68         int l, r;
    69         while( m-- ){
    70             scanf( "%d %d %d", &op, &l, &r );
    71             if( l > r ) swap( l, r );
    72             if( op == 1 ){
    73                 printf( "%I64d
    ", query( l, r, 1, n, 1 ) );
    74             }
    75             if( op == 0 ){
    76                 update( l, r, 1, n, 1 );
    77             }
    78         }
    79         puts( "" );
    80     }
    81     return 0;
    82 }
    View Code

     UVA 12532 Interval Product

    给你n个数,有两种操作,一个是把第 u 个数的值变为 v, 第二种操作是问你 u-v这个区间内所有数相乘的乘积是'+' or '-' or '0',输出符号就好;

    把负数变为-1,把正数变为1,这样就不会相乘溢出了。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<vector>
     7 #include<queue>
     8 
     9 using namespace std;
    10 
    11 #define inf 1e16
    12 #define eps 1e-6
    13 #define LL long long
    14 #define ULL unsigned long long
    15 #define MP make_pair
    16 #define pb push_back
    17 #define lson l, m, rt<<1
    18 #define rson m+1, r, rt<<1|1
    19 #define mnx 100500
    20 
    21 int a[mnx], sum[mnx<<2];
    22 void pushup( int rt ){
    23     sum[rt] = sum[rt<<1] * sum[rt<<1|1];
    24 }
    25 void build( int l, int r, int rt ){
    26     if( l == r ){
    27         sum[rt] = a[l];
    28         return ;
    29     }
    30     int m = ( l + r ) >> 1;
    31     build( lson );
    32     build( rson );
    33     pushup( rt );
    34 }
    35 void update( int u, int v, int l, int r, int rt ){
    36     if( l == r ){
    37         if( v > 0 ) sum[rt] = 1;
    38         else if( v == 0 ) sum[rt] = 0;
    39         else sum[rt] = -1;
    40         return ;
    41     }
    42     int m = ( l + r ) >> 1;
    43     if( u <= m ) update( u, v, lson );
    44     if( u > m ) update( u, v, rson );
    45     pushup( rt );
    46 }
    47 int query( int L, int R, int l, int r, int rt ){
    48     if( L <= l && R >= r )
    49         return sum[rt];
    50     int ret = 1, m = ( l + r ) >> 1;
    51     if( L <= m ) ret *= query( L, R, lson );
    52     if( R > m ) ret *= query( L, R, rson );
    53     return ret;
    54 }
    55 int main(){
    56     //freopen( "tt.txt", "r", stdin );
    57     int n, m;
    58     while( scanf( "%d%d", &n, &m ) != EOF ){
    59         for( int i = 1; i <= n; ++i ){
    60             scanf( "%d", &a[i] );
    61             if( a[i] > 0 ) a[i] = 1;
    62             else if( a[i] == 0 ) a[i] = 0;
    63             else a[i] = -1;
    64         }
    65         build( 1, n, 1 );
    66         while( m -- ){
    67             char s[3];
    68             int u, v;
    69             scanf( "%s%d%d", s, &u, &v );
    70             if( s[0] == 'C' ) update( u, v, 1, n, 1 );
    71             else{
    72                 int ok = query( u, v, 1, n, 1 );
    73                 if( ok == 1 ) printf( "+" );
    74                 else if( ok == 0 ) printf( "0" );
    75                 else printf( "-" );
    76             }
    77         }
    78         puts( "" );
    79     }
    80     return 0;
    81 }
    View Code
  • 相关阅读:
    题解 CF1156A 【Inscribed Figures】
    P1352 没有上司的舞会 题解
    厦门大学附属实验中学第五次OI模拟赛(XDFZOI5)比赛须知
    属于自己的期中考总结
    做题笔记 【模板】字符串哈希
    2018 总结
    做题笔记 图的遍历 P3916
    做题笔记 Splitting into digits CF1104A
    LIS (nlogn)
    标准正交基
  • 原文地址:https://www.cnblogs.com/LJ-blog/p/3909681.html
Copyright © 2011-2022 走看看