【数据结构】【杂题】jzoj 6342.Tiny Counting

较为简单的一个计数题目。


 

Description

 

Input

Output

 

Sample Input

4
1 4 3 2

Sample Output

3

我们可以将这个题目拆开来想:

1.不考虑重复点,求全部情况:

  假设情况1为

  

 

  共p种。 

 

  情况2为

 

  

 

 

  共q种,那么答案ans=qp。

 

2.考虑重复的情况:

 

  重复的情况,无非就是两组共用了同一个端点。

 

  设点(i,si),那么当a=d时,有(c<a<b&&sa<sb&&sa<sc)

 

  在坐标系上就是这样表示的:

 

  

 

   将绿色部分的点数*蓝色部分的点数就得到了这部分的结果。

  其余类似,可以发现ans=pq-(a+b)(c+d),你可以认为abcd表示四个象限。

要离散化,用树状数组搞搞就能出来了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll N=2e5+10;
 5 ll n_,n,ans; 
 6 ll b[N],aa[N],bb[N],cc[N],dd[N];
 7 struct poll{
 8     ll size,idx;
 9 }a[N];
10 ll arr[N];
11 ll lb(ll x){return x&-x;}
12 void add(ll x){for(;x<=n;x+=lb(x))arr[x]++;}
13 ll pre(ll x){ll ans_=0;for(;x;x-=lb(x))ans_+=arr[x];return ans_;}
14 bool cmp(poll x,poll y){
15     return x.size<y.size;
16 }
17 ll read(){
18     ll x=0,f=1;
19     char c=getchar();
20     while(!isdigit(c)){
21         if(c=='-') f=-1;
22         c=getchar(); 
23     } 
24     while(isdigit(c)){
25         x=x*10+c-'0';
26         c=getchar();
27     }
28     return x*f;
29 }
30 int main(){
31     freopen("a.in","r",stdin);
32     freopen("a.out","w",stdout);
33     n_=read();
34     for(ll i=1;i<=n_;i++){
35         a[i].size=read();
36         a[i].idx=i;
37     } 
38     sort(a+1,a+n_+1,cmp);
39     a[0].size=-1;
40     for(ll i=1;i<=n_;i++){
41         if(a[i].size>a[i-1].size) ++n;
42         b[a[i].idx]=n;
43     }
44     ll t1=0,t2=0;
45     for(ll i=1;i<=n_;i++){
46         bb[i]=pre(b[i]-1);
47         dd[i]=pre(n)-pre(b[i]);
48         t1+=bb[i],t2+=dd[i];
49         add(b[i]);
50     }
51     ans=t1*t2;
52     memset(arr,0,sizeof(arr)); 
53     for(ll i=n_;i>=1;i--){
54         cc[i]=pre(b[i]-1);
55         aa[i]=pre(n)-pre(b[i]);
56         ans-=(aa[i]+bb[i])*(cc[i]+dd[i]);
57         add(b[i]);
58     }
59     printf("%lld",ans);
60     return 0;
61 } 

 

posted @ 2019-09-07 21:09  Nelson992770019  阅读(148)  评论(0编辑  收藏  举报