• 树状数组


    链接:https://ac.nowcoder.com/acm/contest/358/D
    来源:牛客网

    出题人的手环
    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 524288K,其他语言1048576K
    64bit IO Format: %lld
    题目描述
    出题人的妹子送了出题人一个手环,这个手环上有 n 个珠子,每个珠子上有一个数。
    有一天,出题人和妹子分手了,想把这个手环从两个珠子间切开,并按顺时针顺序展开成一条链。
    可以发现,这条链一共有 n 种可能性。求这 n 种可能性的逆序对数之积模 1000000007。
    输入描述:
    第一行一个数 n,表示珠子个数。
    接下来一行 n 个数,以顺时针顺序给出每个珠子上的整数
    输出描述:
    一个数,表示答案。
    示例1
    输入

    复制
    4
    1 3 2 3
    输出

    复制
    24
    说明

    一共有 4 种方式:
    1 3 2 3;3 1 3 2;2 3 1 3;3 2 3 1;
    逆序对数分别为 1,3,2,4,积为 24。
    备注:
    n<=200000,-10^9<=珠子上的整数<=10^9。

     1 #define c_1(a) scanf("%d",&a)
     2 #define c_2(a,b) scanf("%d%d",&a,&b)
     3 #define c_3(a,b,c) scanf("%d%d%d",&a,&b,&c)
     4 #define min_2(a,b) a<b?a:b
     5 #define min_3(a,b,c) min_2(min_2(a,b),c)
     6 #define max_2(a,b) a>b?a:b
     7 #define max_3(a,b,c) max_2(max_2(a,b),c)
     8 #define ll long long
     9 #define rint register int
    10 #define mem0(x) memset(x, 0, sizeof(x))
    11 #define mem1(x) memset(x, -1, sizeof(x))
    12 #define lowbit(x)  x&-x
    13 /**inline int read()///神奇的读优
    14 {
    15     int x=0,f=1;char c=getchar();
    16     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    17     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    18     return x*f;
    19 }*/
    20 ///2147483647 -2147483648
    21 ///9223372036854775807 -9223372036854775808
    22 //freopen("input.txt", "r", stdin);
    23 const double PI=acos(-1.0);
    24 const int inf = 0x3f3f3f3f;
    25 const ll inff = 0x3f3f3f3f3f3f3f3f;
    26 const int mod=1000000007;
    27 const int maxn=1e5+5;
    28 map<ll,ll>mp;
    29 //set<ll>st;
    30 //stack<>st;
    31 //queue<>Q;
    32 /***********************************************/
    33 ll c[2*maxn];
    34 ll n;
    35 ll a[2*maxn],b[2*maxn];
    36 
    37 void add(ll x)
    38 {
    39     while(x<=n)
    40     {
    41         c[x]++;
    42         x+=lowbit(x); 
    43     }
    44 }
    45 
    46 ll query(int x)
    47 {
    48     ll sum=0;
    49     while(x>0)
    50     {
    51         sum+=c[x];
    52         x-=lowbit(x);
    53     }
    54     return sum;
    55 }
    56 
    57 int main()
    58 {
    59 
    60     cin>>n;
    61 
    62     for(int i=1;i<=n;i++) cin>>a[i],b[i]=a[i];
    63     sort(a+1,a+1+n);
    64     a[0]=a[1];
    65     ll an=1;
    66     for(int i=1;i<=n;i++)
    67     {
    68         if(a[i]==a[i-1]) mp[a[i]]=an;
    69         else mp[a[i]]=(++an);
    70     }
    71     ll sum=0;
    72     for(int i=1;i<=n;i++) 
    73     {
    74         b[i]=mp[b[i]];//转化为b[i],就可以用数组存了,之后维护树状数组(计算前n项和)
    75         add(b[i]);
    76         sum+=(i-query(b[i]));
    77         sum%=mod;
    78     }
    79 
    80     ll ans=sum;
    81     for(int i=1;i<n;i++)
    82     {
    83         ll p=query(b[i]);
    84         sum+=(n-p);
    85         sum-=query(b[i]-1);
    86         sum=(sum+mod)%mod;
    87         ans=(ans*sum)%mod;
    88     }
    89     cout<<ans<<endl;
    90     return 0;
    91 }
    代码

     进阶:差分法

    树状数组差分修改区间,博客

    来着落谷P3368 【模板】树状数组 2

    题目描述

    如题,已知一个数列,你需要进行下面两种操作:

    1.将某区间每一个数数加上x

    2.求出某一个数的值

    输入输出格式

    输入格式:

    第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。

    第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

    接下来M行每行包含2或4个整数,表示一个操作,具体如下:

    操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k

    操作2: 格式:2 x 含义:输出第x个数的值

    输出格式:

    输出包含若干行整数,即为所有操作2的结果。

    输入输出样例

    输入样例#1: 复制
    5 5
    1 5 4 2 3
    1 2 4 2
    2 3
    1 1 5 -1
    1 3 5 7
    2 4
    输出样例#1: 复制
    6
    10

    说明

    时空限制:1000ms,128M

    数据规模:

    对于30%的数据:N<=8,M<=10

    对于70%的数据:N<=10000,M<=10000

    对于100%的数据:N<=500000,M<=500000

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <string>
      6 #include <vector>
      7 #include <stack>
      8 #include <map>
      9 #include <set>
     10 #include <queue>
     11 #include <list>
     12 #include <cstdlib>
     13 #include <iterator>
     14 #include <cmath>
     15 #include <iomanip>
     16 #include <bitset>
     17 #include <cctype>
     18 //#include <bits/stdc++.h>
     19 
     20 using namespace std;
     21 #define c_1(a) scanf("%d",&a)
     22 #define c_2(a,b) scanf("%d%d",&a,&b)
     23 #define c_3(a,b,c) scanf("%d%d%d",&a,&b,&c)
     24 #define min_2(a,b) a<b?a:b
     25 #define min_3(a,b,c) min_2(min_2(a,b),c)
     26 #define max_2(a,b) a>b?a:b
     27 #define max_3(a,b,c) max_2(max_2(a,b),c)
     28 #define ll long long
     29 #define rint register int
     30 #define mem0(x) memset(x, 0, sizeof(x))
     31 #define mem1(x) memset(x, -1, sizeof(x))
     32 #define lowbit(x)  x&-x
     33 /**inline int read()///神奇的读优
     34 {
     35     int x=0,f=1;char c=getchar();
     36     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
     37     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
     38     return x*f;
     39 }*/
     40 ///2147483647 -2147483648
     41 ///9223372036854775807 -9223372036854775808
     42 //freopen("input.txt", "r", stdin);
     43 const double PI=acos(-1.0);
     44 const int inf = 0x3f3f3f3f;
     45 const ll inff = 0x3f3f3f3f3f3f3f3f;
     46 const int mod=1000000007;
     47 const int maxn=6e5+5;
     48 map<int,int>mp1;
     49 map<int,int>mp;
     50 //set<ll>st;
     51 //stack<>st;
     52 //queue<>Q;
     53 /***********************************************/
     54 
     55 int c[maxn],n,m,a[maxn],b[maxn],d[maxn];
     56 
     57 void add(int x,int y)
     58 {
     59     while(x<=n)
     60     {
     61         c[x]+=y;
     62         x+=lowbit(x);
     63     }
     64 }
     65 
     66 ll summ(int x)
     67 {
     68     ll su=0;
     69     while(x>0)
     70     {
     71         su+=c[x];
     72         x-=lowbit(x);
     73     }
     74     return su;
     75 }
     76 
     77 
     78 int main()
     79 {
     80     cin>>n>>m;
     81     for(int i=1;i<=n;i++) cin>>a[i];
     82     for(int i=1;i<=n;i++) d[i]=a[i]-a[i-1],add(i,d[i]);
     83     while(m--)
     84     {
     85         int op,x,y,k;
     86         cin>>op;
     87         if(op==1)
     88         {
     89             cin>>x>>y>>k;
     90             add(x,k);
     91             add(y+1,-k);
     92         }
     93         else 
     94         {
     95             cin>>x;
     96             cout<<summ(x)<<endl;
     97         }
     98     }
     99     return 0;
    100 }
    101 /*
    102 5
    103 2 3 6 2 1
    104 
    105 0 1 2 0 0
    106 */
    代码
  • 相关阅读:
    [Web安全] XXE漏洞攻防学习(中)
    [Web安全] XXE漏洞攻防学习(上)
    [转]kali中eth0网卡突然消失解决方案
    [漏洞复现]CVE-2018-4887 Flash 0day
    [漏洞复现]CVE-2010-2883 Adobe Reader 打开pdf电脑即刻中招
    [漏洞复现] CVE-2017-11882 通杀所有Office版本
    墨菲定律:Mac本硬盘坏了
    独立思考
    阅读书单
    2020未来小思考
  • 原文地址:https://www.cnblogs.com/liuyongliu/p/10295394.html
Copyright © 2020-2023  润新知