链接: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的结果。
输入输出样例
说明
时空限制: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 */