树状数组习题集

1、HDU2689 Sort it

求最少的步数使得序列升序,无重复数据,每步只能交换两个相邻的数。树状数组求逆序对。

 1 #include<iostream>
 2 #include<sstream>
 3 #include<fstream>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<iomanip>
 7 #include<cstdlib>
 8 #include<cctype>
 9 #include<vector>
10 #include<string>
11 #include<cmath>
12 #include<ctime>
13 #include<stack>
14 #include<queue>
15 #include<map>
16 #include<set>
17 #define mem(a,b) memset(a,b,sizeof(a))
18 #define random(a,b) (rand()%(b-a+1)+a)
19 #define ll long long
20 #define ull unsigned long long
21 #define e 2.71828182
22 #define Pi acos(-1.0)
23 #define ls(rt) (rt<<1)
24 #define rs(rt) (rt<<1|1)
25 #define lowbit(x) (x&(-x))
26 using namespace std;
27 const int MAXN=5000+5;
28 int a[MAXN],Tree[MAXN],n;
29 inline void update(int x,int k)
30 {
31     for(int i=x;i<=n;i+=lowbit(i))
32     Tree[i]+=k;
33 }
34 int getsum(int x)
35 {
36     int ans=0;
37     for(int i=x;i>=1;i-=lowbit(i))
38     ans+=Tree[i];
39     return ans;
40 }
41 int read()
42 {
43     int s=1,x=0;
44     char ch=getchar();
45     while(!isdigit(ch)) {if(ch=='-') s=-1;ch=getchar();}
46     while(isdigit(ch)) {x=10*x+ch-'0';ch=getchar();}
47     return x*s;
48 }
49 int main()
50 {
51     while(~scanf("%d",&n))
52     {
53         int ans=0;
54         mem(Tree,0);
55         for(int i=1;i<=n;++i) 
56         {
57             a[i]=read();
58             update(a[i],1);
59             ans+=i-getsum(a[i]);
60         }
61         cout<<ans<<endl;    
62     }
63 }
View Code

 

2、HDU4911 Inversion

最多移动n步,每步只能交换两个相邻的数,求过程中最少的逆序数。求出逆序数后和k进行比较,输出差值或0。

把一个序列交换成递增序列所需的最少步数即逆序数。

这题还用到了离散化。

 1 #include<iostream>
 2 #include<sstream>
 3 #include<fstream>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<iomanip>
 7 #include<cstdlib>
 8 #include<cctype>
 9 #include<vector>
10 #include<string>
11 #include<cmath>
12 #include<ctime>
13 #include<stack>
14 #include<queue>
15 #include<map>
16 #include<set>
17 #define mem(a,b) memset(a,b,sizeof(a))
18 #define random(a,b) (rand()%(b-a+1)+a)
19 #define ll long long
20 #define ull unsigned long long
21 #define e 2.71828182
22 #define Pi acos(-1.0)
23 #define ls(rt) (rt<<1)
24 #define rs(rt) (rt<<1|1)
25 #define lowbit(x) (x&(-x))
26 using namespace std;
27 const int MAXN=1e5+5;
28 int Tree[MAXN],Hash[MAXN],n,k;
29 struct node
30 {
31     int val,pos;    
32     bool operator < (node& a)
33     {
34         if(val!=a.val) return val<a.val;
35         return pos<a.pos;
36     }
37 }b[MAXN];
38 void update(int x,int k)
39 {
40     for(int i=x;i<=n;i+=lowbit(i))
41     Tree[i]+=k;
42 }
43 int getsum(int x)
44 {
45     int ans=0;
46     for(int i=x;i>=1;i-=lowbit(i))
47     ans+=Tree[i];
48     return ans;
49 }
50 int read()
51 {
52     int s=1,x=0;
53     char ch=getchar();
54     while(!isdigit(ch)) {if(ch=='-') s=-1;ch=getchar();}
55     while(isdigit(ch)) {x=10*x+ch-'0';ch=getchar();}
56     return x*s;
57 }
58 int main()
59 {
60     while(~scanf("%d%d",&n,&k))
61     {
62         for(int i=1;i<=n;++i) 
63         b[i].val=read(),b[i].pos=i;
64         mem(Tree,0);
65         sort(b+1,b+n+1);
66         /*for(int i=1;i<=n;++i)
67         Hash[b[i].pos]=i;*/ //无重复数据
68         //有重复数据 
69         int cnt=1;
70         Hash[b[1].pos]=1;
71         for(int i=2;i<=n;++i)
72         {
73             if(b[i].val!=b[i-1].val) Hash[b[i].pos]=++cnt;
74             else Hash[b[i].pos]=cnt;
75         }
76         ll num=0;
77         //离散后的数据 
78         //for(int i=1;i<=n;++i) cout<<Hash[i]<<' ';cout<<endl;
79         for(int i=1;i<=n;++i)
80         {
81             update(Hash[i],1);
82             num+=(i-getsum(Hash[i]));
83         }
84         if(num<k) cout<<0<<endl;
85         else cout<<num-k<<endl;
86     }
87     return 0;
88 }
View Code

 

3、HDU1394 Minimum Inversion Number

相当于环状序列找到点切成链状的最少逆序数。

 1 #include<iostream>
 2 #include<sstream>
 3 #include<fstream>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<iomanip>
 7 #include<cstdlib>
 8 #include<cctype>
 9 #include<vector>
10 #include<string>
11 #include<cmath>
12 #include<ctime>
13 #include<stack>
14 #include<queue>
15 #include<map>
16 #include<set>
17 #define mem(a,b) memset(a,b,sizeof(a))
18 #define random(a,b) (rand()%(b-a+1)+a)
19 #define ll long long
20 #define ull unsigned long long
21 #define e 2.71828182
22 #define Pi acos(-1.0)
23 #define ls(rt) (rt<<1)
24 #define rs(rt) (rt<<1|1)
25 #define lowbit(x) (x&(-x))
26 using namespace std;
27 const int MAXN=5e3+5;
28 int Tree[MAXN],a[MAXN],n;
29 void update(int x,int v)
30 {
31     for(int i=x;i<=n;i+=lowbit(i))
32     Tree[i]+=v;
33 }
34 int getsum(int x)
35 {
36     int ans=0;
37     for(int i=x;i>=1;i-=lowbit(i))
38     ans+=Tree[i];
39     return ans;
40 }
41 int read()
42 {
43     int s=1,x=0;
44     char ch=getchar();
45     while(!isdigit(ch)) {if(ch=='-') s=-1;ch=getchar();}
46     while(isdigit(ch)) {x=10*x+ch-'0';ch=getchar();}
47     return x*s;
48 }
49 int main()
50 {
51     while(~scanf("%d",&n))
52     {
53         int ans=0;
54         mem(Tree,0);
55         for(int i=1;i<=n;++i)
56         {
57             a[i]=read()+1;
58             update(a[i],1);
59             ans+=i-getsum(a[i]);
60         }
61         //比a[1]小的数有a[1]-1个,将a[1]移至末尾逆序数会减少a[1]-1 ;
62         //但同时,比a[1]大的数有n-a[1]个,逆序数会加n-a[1] 
63         int tmp=ans;
64         //cout<<ans<<endl;
65         for(int i=1;i<=n;++i)
66         {    
67             tmp=tmp-(a[i]-1)+(n-a[i]);
68             ans=min(ans,tmp);
69         }
70         cout<<ans<<endl;
71     }
72     return 0;
73 }
View Code

 

4、VJ Aizu1395 What Goes Up Must Come Down

对每个数来说,只有两种情况,要么参与非递减部分要么参与非递增部分,对于前者它要移的次数就是在它之前与他构成的逆序对数,对于后者它要移的次数就是在它之后与他构成的逆序对数,那我们取较小的加入到答案就做完了。

求一个数的后面比它小的数可以用上述三题的方法将序列倒过来求。

可以不用离散化的,练一下。

 1 #include<iostream>
 2 #include<sstream>
 3 #include<fstream>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<iomanip>
 7 #include<cstdlib>
 8 #include<cctype>
 9 #include<vector>
10 #include<string>
11 #include<cmath>
12 #include<ctime>
13 #include<stack>
14 #include<queue>
15 #include<map>
16 #include<set>
17 #define mem(a,b) memset(a,b,sizeof(a))
18 #define random(a,b) (rand()%(b-a+1)+a)
19 #define ll long long
20 #define ull unsigned long long
21 #define e 2.71828182
22 #define Pi acos(-1.0)
23 #define ls(rt) (rt<<1)
24 #define rs(rt) (rt<<1|1)
25 #define lowbit(x) (x&(-x))
26 using namespace std;
27 const int MAXN=1e5+5;
28 int Tree[MAXN],Hash[MAXN],n;
29 int pre[MAXN],suf[MAXN];
30 struct node
31 {
32     int val,pos;
33     bool operator < (node& a)
34     {
35         if(val!=a.val) return val<a.val;
36         return pos<a.pos;    
37     } 
38 }a[MAXN];
39 void update(int x,int v)
40 {
41     for(int i=x;i<=n;i+=lowbit(i))
42     Tree[i]+=v;
43 }
44 int getsum(int x)
45 {
46     int ans=0;
47     for(int i=x;i>=1;i-=lowbit(i))
48     ans+=Tree[i];
49     return ans;
50 }
51 int read()
52 {
53     int s=1,x=0;
54     char ch=getchar();
55     while(!isdigit(ch)) {if(ch=='-') s=-1;ch=getchar();}
56     while(isdigit(ch)) {x=10*x+ch-'0';ch=getchar();}
57     return x*s;
58 }
59 int main()
60 {
61     n=read();
62     for(int i=1;i<=n;++i)
63     a[i].val=read(),a[i].pos=i;
64     sort(a+1,a+n+1);
65     int cnt=1;
66     Hash[a[1].pos]=1;
67     for(int i=2;i<=n;++i)
68     if(a[i].val==a[i-1].val) Hash[a[i].pos]=cnt;
69     else Hash[a[i].pos]=++cnt;
70     for(int i=1;i<=n;++i)
71     {
72         update(Hash[i],1);
73         pre[i]=i-getsum(Hash[i]);
74     }
75     mem(Tree,0);
76     for(int i=n;i>=1;i--)
77     {
78         update(Hash[i],1);
79         suf[i]=(n-i+1)-getsum(Hash[i]);
80     }
81     ll ans=0;
82     /*for(int i=1;i<=n;++i)
83     {
84         cout<<pre[i]<<' '<<suf[i]<<endl;
85     }*/
86     for(int i=1;i<=n;++i)
87     ans+=min(pre[i],suf[i]);
88     cout<<ans<<endl;
89 }
View Code

 

转载于:https://www.cnblogs.com/wangzhebufangqi/p/11301647.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值