树状数组专题

前言:树状数组的最基本功能就是求比某点x小的点的个数(这里的比较是抽象的概念,可以使数的大小,坐标的大小,质量的大小等)


Link1:http://acm.hdu.edu.cn/showproblem.php?pid=1541

Stars

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5234    Accepted Submission(s): 2064


Problem Description
Astronomers often examine star maps where stars are represented by points on a plane and each star has Cartesian coordinates. Let the level of a star be an amount of the stars that are not higher and not to the right of the given star. Astronomers want to know the distribution of the levels of the stars. 



For example, look at the map shown on the figure above. Level of the star number 5 is equal to 3 (it's formed by three stars with a numbers 1, 2 and 4). And the levels of the stars numbered by 2 and 4 are 1. At this map there are only one star of the level 0, two stars of the level 1, one star of the level 2, and one star of the level 3. 

You are to write a program that will count the amounts of the stars of each level on a given map.
 

Input
The first line of the input file contains a number of stars N (1<=N<=15000). The following N lines describe coordinates of stars (two integers X and Y per line separated by a space, 0<=X,Y<=32000). There can be only one star at one point of the plane. Stars are listed in ascending order of Y coordinate. Stars with equal Y coordinates are listed in ascending order of X coordinate.
 

Output
The output should contain N lines, one number per line. The first line contains amount of stars of the level 0, the second does amount of stars of the level 1 and so on, the last line contains amount of stars of the level N-1.
 

Sample Input
      
      
5 1 1 5 1 7 1 3 3 5 5
 

Sample Output
      
      
1 2 1 1 0
 

Source
 

Recommend
LL   |   We have carefully selected several similar problems for you:   1166  1394  3450  1542  1255 
 

Statistic |  Submit |  Discuss |  Note

题意:天空中有一些星星,这些星星都在不同的位置,每个星星有个坐标。 如果一个星星的左下方(包含正左和正下)有k颗星星,就说这颗星星是k级的.比如,在下面的例图中,星星5是3级的(1,2,4在它左下)。 星星2,4是1级的。例图中有1个0级,2个1级,1个2级,1个3级的星。求出各个级别的星星的个数。

算法分析:直接最普通的树状数组即可解决,注意题目中给出的坐标是从0开始的,所以在读入坐标是要+1后在进行处理。


#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<queue>
#define MAX 32001
using namespace std;
int c[MAX],ans[MAX];
int n;
int lowbit(int p)
{
	return p&(-p);
}
int sum(int p)
{
	int s=0;
	while(p>0)
	{
		s+=c[p];
		p-=lowbit(p);
	}
	return s;
}
void update(int p,int n,int k)
{
	while(p<=n)
	{
		c[p]+=k;
		p+=lowbit(p);
	}
}
int main()
{
	int x,y,i,leval;
	while(scanf("%d",&n)!=EOF)
	{
		memset(c,0,sizeof(c));
    	memset(ans,0,sizeof(ans));
	for(i=1;i<=n;i++)
	{
		scanf("%d%d",&x,&y);
		leval = sum(x+1);
		ans[leval]++;
		update(x+1,MAX,1);
	}
	for(i=0;i<=n-1;i++)
	{
		printf("%d\n",ans[i]);
	}
	}
	return 0;
 }


Link2:http://poj.org/problem?id=2182

Lost Cows
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 9500 Accepted: 6127

Description

N (2 <= N <= 8,000) cows have unique brands in the range 1..N. In a spectacular display of poor judgment, they visited the neighborhood 'watering hole' and drank a few too many beers before dinner. When it was time to line up for their evening meal, they did not line up in the required ascending numerical order of their brands. 

Regrettably, FJ does not have a way to sort them. Furthermore, he's not very good at observing problems. Instead of writing down each cow's brand, he determined a rather silly statistic: For each cow in line, he knows the number of cows that precede that cow in line that do, in fact, have smaller brands than that cow. 

Given this data, tell FJ the exact ordering of the cows. 

Input

* Line 1: A single integer, N 

* Lines 2..N: These N-1 lines describe the number of cows that precede a given cow in line and have brands smaller than that cow. Of course, no cows precede the first cow in line, so she is not listed. Line 2 of the input describes the number of preceding cows whose brands are smaller than the cow in slot #2; line 3 describes the number of preceding cows whose brands are smaller than the cow in slot #3; and so on. 

Output

* Lines 1..N: Each of the N lines of output tells the brand of a cow in line. Line #1 of the output tells the brand of the first cow in line; line 2 tells the brand of the second cow; and so on.

Sample Input

5
1
2
1
0

Sample Output

2
4
5
3
1

Source



思想1:根据所给的数据,从后往前找牛,假如最后一头牛的前面有a个编号比它小的,那么它的编号就肯定是a+1。然后把找到的牛从原先的“牛队”中删去。再找倒数第二头牛,假如它前面有b个编号比它小的,那么,它的编号肯定就是剩下的牛的牛的第b+1个,然后再把该牛删除,以此类推……(思想表达参考自http://blog.csdn.net/hackerain/article/details/6261073)

代码1:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<map>
using namespace std;
#define MAX 32001
int c[MAX],a[MAX],ans[MAX],n;
int lowbit(int p)
{
	return p&(-p);
}
int sum(int p)
{
	int s=0;
	while(p>0)
	{
		s+=c[p];
		p-=lowbit(p);
	}
	return s;
}
void update(int p,int k)
{
	while(p<=n)
	{
		c[p]+=k;
		p+=lowbit(p);
	}
}
int Bsearch(int x)
{
	int mid,l,r;
	l=1;
	r=n;

	while(l<=r)
	{
		mid=(l+r)>>1;
		if(sum(mid)<x)
		{
			l=mid+1;
			
		}
		else
		{
			r=mid-1;
		}
	}
	 return l;
	
}
int main()
{
	int i;
	scanf("%d",&n);
	a[1]=0;
	update(1,1);//初始化树状数组1,2,3,……n
	for(i=2;i<=n;i++)
	{
		scanf("%d",&a[i]);
		update(i,1);
	}
	for(i=n;i>=1;i--)
	{
		ans[i]=Bsearch(a[i]+1);//树状数组里面的元素的索引值就是编号
		update(ans[i],-1);
	}
	for(i=1;i<=n;i++)
	{
		printf("%d\n",ans[i]);
	}
	return 0;
}




思想2:直接模拟。(参考自http://lovekid1987.blog.163.com/blog/static/115184210200941263259639/)

代码2:

<span style="font-size:18px;">#include <iostream>
using namespace std;
#define N 8000
int a[N];//用来存储输入的数据
int b[N+1];//用来标记对应编号的牛是否已经确定
int c[N];//用来存储牛的编号
int main()
{
	//freopen("in.txt","r",stdin);
	int i,j;
	while(cin>>a[0])
	{
		int count=0;//用来计算牛排在第几位
		memset(b,1,sizeof(b));
		for(i=1;i<a[0];i++)
			cin>>a[i];
		for(i=a[0]-1;i>=0;i--)
		{
			if(i)
			{//从后往前找牛
				for(j=1;j<=a[0];j++)
				{
					if(b[j])
						++count;
					if(count==a[i]+1)
					{
						b[j]=0;
						c[i]=j;
						count=0;
						break;
					}
				}
			}
			else
			{//找排在第一的牛的编号
				for(j=1;j<=a[0];j++)
					if(b[j])
						c[i]=j;
			}
		}
		for(i=0;i<a[0];i++)
			cout<<c[i]<<endl;
	}
	return 0;
}</span>


代码:3:

#include<stdio.h>
#include<string.h>
const int MAXNUM=8002;
int input[MAXNUM];
void Init(){
 memset(input,0,sizeof(input));
}
int main(){
 //freopen("C:\\Documents and Settings\\Administrator\\桌面\\in.txt","r",stdin);
 int n,i,j;
 while(scanf("%d",&n)!=EOF){
  Init();
  for(i=2;i<=n;i++){
   scanf("%d",&input[i]);
   for(j=1;j<i;j++)
    if(input[j]>=input[i])
     input[j]++;
  }
  for(i=1;i<=n;i++)
   printf("%d\n",input[i]+1);
 }
}

Link3:http://poj.org/problem?id=2481


Cows
Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 13480 Accepted: 4459

Description

Farmer John's cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one-dimensional number line) in his field is particularly good. 

Farmer John has N cows (we number the cows from 1 to N). Each of Farmer John's N cows has a range of clover that she particularly likes (these ranges might overlap). The ranges are defined by a closed interval [S,E]. 

But some cows are strong and some are weak. Given two cows: cow i and cow j, their favourite clover range is [Si, Ei] and [Sj, Ej]. If Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj, we say that cow i is stronger than cow j

For each cow, how many cows are stronger than her? Farmer John needs your help!

Input

The input contains multiple test cases. 
For each test case, the first line is an integer N (1 <= N <= 10 5), which is the number of cows. Then come N lines, the i-th of which contains two integers: S and E(0 <= S < E <= 10 5) specifying the start end location respectively of a range preferred by some cow. Locations are given as distance from the start of the ridge. 

The end of the input contains a single 0.

Output

For each test case, output one line containing n space-separated integers, the i-th of which specifying the number of cows that are stronger than cow i

Sample Input

3
1 2
0 3
3 4
0

Sample Output

1 0 0

Hint

Huge input and output,scanf and printf is recommended.

Source

POJ Contest,Author:Mathematica@ZSU

[Submit]   [Go Back]   [Status]   [Discuss]

题意:给出每头牛的S[]与E[]当Si<=Sj&&Ej<=Ei说明i牛比j牛强壮,找出比i(1...n)强壮的牛的个数
解题思想:Starts题的变形而已。就多了排序离散化。。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<queue>
#define MAX 100010
using namespace std;
int c[MAX],ans[MAX];
int n;
struct node{
	int x;
	int y;
	int ord;
}a[MAX];
bool cmp(node a,node b)
{
	if(a.y!=b.y)
	{
		return a.y>b.y;
	}
	return a.x<b.x;
}
int lowbit(int p)
{
	return p&(-p);
 } 
 int sum(int p)
 {
 	int s=0;
 	while(p>0)
 	{
 		s+=c[p];
 		p-=lowbit(p);
	 }
	 return s;
 }
 void up(int p,int k)
 {
 	while(p<=MAX)
 	{
 		c[p]+=k;
 		p+=lowbit(p);
	 }
 }
 int main()
 {
 	int i;
 	while(scanf("%d",&n)&&n)
 	{
 		memset(c,0,sizeof(c));
 		memset(ans,0,sizeof(ans));
 		for(i=1;i<=n;i++)
 		{
 			scanf("%d%d",&a[i].x,&a[i].y);
 			a[i].x++;
 			a[i].y++;
 			a[i].ord=i;
		 }
		 sort(a+1,a+n+1,cmp);
		 for(i=1;i<=n;i++)
		 {
		 	if(i>=2&&a[i].x==a[i-1].x&&a[i].y==a[i-1].y)
		 	{
		 		ans[a[i].ord]=ans[a[i-1].ord];
			 }
			 else
			 {
			 	ans[a[i].ord]=sum(a[i].x);
			 }
			 up(a[i].x,1);
		 }
		 for(i=1;i<n;i++)
		 {
		 	printf("%d ",ans[i]);
		 }
		 printf("%d\n",ans[n]);
	 }
 	return 0;
 }

Link4: http://poj.org/problem?id=3067


Japan
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 21797 Accepted: 5891

Description

Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Japan is tall island with N cities on the East coast and M cities on the West coast (M <= 1000, N <= 1000). K superhighways will be build. Cities on each coast are numbered 1, 2, ... from North to South. Each superhighway is straight line and connects city on the East coast with city of the West coast. The funding for the construction is guaranteed by ACM. A major portion of the sum is determined by the number of crossings between superhighways. At most two superhighways cross at one location. Write a program that calculates the number of the crossings between superhighways.

Input

The input file starts with T - the number of test cases. Each test case starts with three numbers – N, M, K. Each of the next K lines contains two numbers – the numbers of cities connected by the superhighway. The first one is the number of the city on the East coast and second one is the number of the city of the West coast.

Output

For each test case write one line on the standard output: 
Test case (case number): (number of crossings)

Sample Input

1
3 4 4
1 4
2 3
3 2
3 1

Sample Output

Test case 1: 5

Source

[Submit]   [Go Back]   [Status]   [Discuss]


题意:左边有n个城市,右边有m个城市,建k条道路,问有这k条道路中有多少个交点。


分析:将城市按x和y从小到大排序,对于每条道路,求前面有多少个y比当前的y大的,累加起来即可。即求逆序数,可以用树状数组实现。


求逆序数的思路:


可以把数一个个插入到树状数组中, 每插入一个数, 统计小于等于他的数的个数,对应的逆序为 i- sum( data[i] ),其中 i 为当前已经插入的数的个数, sum( data[i] )为比 小于等于data[i] 的数的个数,i- sum( data[i] ) 即比 data[i] 大的个数, 即逆序的个数。最后需要把所有逆序数求和,就是在插入的过程中边插入边求和。


另外这题要注意会超int,要用64位才能过。



#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<queue>
#define MAX 1010
using namespace std;
int c[MAX];
__int64 ans;
int n;
struct node{
	int x;
	int y;
	int ord;
}a[MAX*MAX];
bool cmp(node a,node b)
{
	if(a.x!=b.x)
	{
		return a.x<b.x;
	}
	return a.y<b.y;
}
int lowbit(int p)
{
	return p&(-p);
 } 
 int sum(int p)
 {
 	int s=0;
 	while(p>0)
 	{
 		s+=c[p];
 		p-=lowbit(p);
	 }
	 return s;
 }
 void up(int p,int k)
 {
 	while(p<=MAX)
 	{
 		c[p]+=k;
 		p+=lowbit(p);
	 }
 }
 int main()
 {
 	int i,t,m,k,cnt;
    scanf("%d",&t);
 		for(cnt=1;cnt<=t;cnt++)
 		{
 			memset(c,0,sizeof(c));
 	        ans=0;
 	        scanf("%d%d%d",&k,&m,&n);
 	    	for(i=1;i<=n;i++)
 	    	{
 	    		scanf("%d%d",&a[i].x,&a[i].y);
	    	 }
	    	 sort(a+1,a+n+1,cmp);
	    	 for(i=1;i<=n;i++)
	    	 {
		    	 up(a[i].y,1);
		    	 ans+=i-sum(a[i].y);
	    	 }
	    	 printf("Test case %d: %I64d\n",cnt,ans);
		}
 	return 0;
 }

Link5:http://poj.org/problem?id=1195


Mobile phones
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 15693 Accepted: 7236

Description

Suppose that the fourth generation mobile phone base stations in the Tampere area operate as follows. The area is divided into squares. The squares form an S * S matrix with the rows and columns numbered from 0 to S-1. Each square contains a base station. The number of active mobile phones inside a square can change because a phone is moved from a square to another or a phone is switched on or off. At times, each base station reports the change in the number of active phones to the main base station along with the row and the column of the matrix. 

Write a program, which receives these reports and answers queries about the current total number of active mobile phones in any rectangle-shaped area. 

Input

The input is read from standard input as integers and the answers to the queries are written to standard output as integers. The input is encoded as follows. Each input comes on a separate line, and consists of one instruction integer and a number of parameter integers according to the following table. 

The values will always be in range, so there is no need to check them. In particular, if A is negative, it can be assumed that it will not reduce the square value below zero. The indexing starts at 0, e.g. for a table of size 4 * 4, we have 0 <= X <= 3 and 0 <= Y <= 3. 

Table size: 1 * 1 <= S * S <= 1024 * 1024 
Cell value V at any time: 0 <= V <= 32767 
Update amount: -32768 <= A <= 32767 
No of instructions in input: 3 <= U <= 60002 
Maximum number of phones in the whole table: M= 2^30 

Output

Your program should not answer anything to lines with an instruction other than 2. If the instruction is 2, then your program is expected to answer the query by writing the answer as a single line containing a single integer to standard output.

Sample Input

0 4
1 1 2 3
2 0 0 2 2 
1 1 1 2
1 1 2 -1
2 1 1 2 3 
3

Sample Output

3
4

Source

[Submit]   [Go Back]   [Status]   [Discuss]


AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
const int MAX=1030;
int c[MAX][MAX],s;
int lowbit(int p)
{
	return p&(-p);
}
__int64 sum(int x,int y)
{
	__int64 s=0;
	for(int i=x;i>0;i-=lowbit(i))
	{
		for(int j=y;j>0;j-=lowbit(j))
		{
			s+=c[i][j];
		}
	}
	return s;
}
void up(int x,int y,int k)
{
	for(int i=x;i<=s;i+=lowbit(i))
	{
		for(int j=y;j<=s;j+=lowbit(j))
		{
			c[i][j]+=k;
		}
	}
}
int main()
{
	int n,x1,y1,x2,y2,k;
	__int64 ans;
	scanf("%d%d",&n,&s);
	memset(c,0,sizeof(c));
	while(1)
	{
		scanf("%d",&n);
		if(n==1)
		{
			scanf("%d%d%d",&x1,&y1,&k);
			up(x1+1,y1+1,k);
		}
		else if(n==2)
		{
			scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
			ans=sum(x2+1,y2+1)-sum(x2+1,y1)-sum(x1,y2+1)+sum(x1,y1);
			printf("%I64d\n",ans);
		}
		else
		{
			break;
		}
	}
	
	return 0;
 } 


Link6: http://poj.org/problem?id=2029


Get Many Persimmon Trees
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 3712 Accepted: 2413

Description

Seiji Hayashi had been a professor of the Nisshinkan Samurai School in the domain of Aizu for a long time in the 18th century. In order to reward him for his meritorious career in education, Katanobu Matsudaira, the lord of the domain of Aizu, had decided to grant him a rectangular estate within a large field in the Aizu Basin. Although the size (width and height) of the estate was strictly specified by the lord, he was allowed to choose any location for the estate in the field. Inside the field which had also a rectangular shape, many Japanese persimmon trees, whose fruit was one of the famous products of the Aizu region known as 'Mishirazu Persimmon', were planted. Since persimmon was Hayashi's favorite fruit, he wanted to have as many persimmon trees as possible in the estate given by the lord. 
For example, in Figure 1, the entire field is a rectangular grid whose width and height are 10 and 8 respectively. Each asterisk (*) represents a place of a persimmon tree. If the specified width and height of the estate are 4 and 3 respectively, the area surrounded by the solid line contains the most persimmon trees. Similarly, if the estate's width is 6 and its height is 4, the area surrounded by the dashed line has the most, and if the estate's width and height are 3 and 4 respectively, the area surrounded by the dotted line contains the most persimmon trees. Note that the width and height cannot be swapped; the sizes 4 by 3 and 3 by 4 are different, as shown in Figure 1. 
 
Figure 1: Examples of Rectangular Estates

Your task is to find the estate of a given size (width and height) that contains the largest number of persimmon trees.

Input

The input consists of multiple data sets. Each data set is given in the following format. 


W H 
x1 y1 
x2 y2 
... 
xN yN 
S T 

N is the number of persimmon trees, which is a positive integer less than 500. W and H are the width and the height of the entire field respectively. You can assume that both W and H are positive integers whose values are less than 100. For each i (1 <= i <= N), xi and yi are coordinates of the i-th persimmon tree in the grid. Note that the origin of each coordinate is 1. You can assume that 1 <= xi <= W and 1 <= yi <= H, and no two trees have the same positions. But you should not assume that the persimmon trees are sorted in some order according to their positions. Lastly, S and T are positive integers of the width and height respectively of the estate given by the lord. You can also assume that 1 <= S <= W and 1 <= T <= H. 

The end of the input is indicated by a line that solely contains a zero. 

Output

For each data set, you are requested to print one line containing the maximum possible number of persimmon trees that can be included in an estate of the given size.

Sample Input

16
10 8
2 2
2 5
2 7
3 3
3 8
4 2
4 5
4 8
6 4
6 7
7 5
7 8
8 1
8 4
9 6
10 3
4 3
8
6 4
1 2
2 1
2 4
3 4
4 2
5 3
6 1
6 2
3 2
0

Sample Output

4
3

Source

[Submit]   [Go Back]   [Status]   [Discuss]


AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
const int MAX=101;
int c[MAX][MAX],w,h;
int lowbit(int p)
{
	return p&(-p);
}
int sum(int x,int y)
{
	int s=0;
	for(int i=x;i>0;i-=lowbit(i))
	{
		for(int j=y;j>0;j-=lowbit(j))
		{
			s+=c[i][j];
		}
	}
	return s;
}
void up(int x,int y,int k)
{
	for(int i=x;i<=w;i+=lowbit(i))
	{
		for(int j=y;j<=h;j+=lowbit(j))
		{
			c[i][j]+=k;
		}
	}
}
int main()
{
	int i,j,x,y,ans,s,t,n;
	//freopen("C:\\1.txt","r",stdin);
	while(~scanf("%d",&n))
	{
		if(n==0)
		{
			break;
		}
		memset(c,0,sizeof(c));
		scanf("%d%d",&w,&h);
		for(i=1;i<=n;i++)
		{
			scanf("%d%d",&x,&y);
			up(x,y,1);
		}
		scanf("%d%d",&s,&t);
		ans=0;
		for(i=s;i<=w;i++)
		{
			for(j=t;j<=h;j++)
			{
				ans=max(ans,sum(i,j)-sum(i,j-t)-sum(i-s,j)+sum(i-s,j-t));
			}
		}
		printf("%d\n",ans);
		
	}
	return 0;
 } 


Link7:http://acm.hdu.edu.cn/showproblem.php?pid=2852


KiKi's K-Number

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2801    Accepted Submission(s): 1276


Problem Description
For the k-th number, we all should be very familiar with it. Of course,to kiki it is also simple. Now Kiki meets a very similar problem, kiki wants to design a container, the container is to support the three operations.

Push: Push a given element e to container

Pop: Pop element of a given e from container

Query: Given two elements a and k, query the kth larger number which greater than a in container;

Although Kiki is very intelligent, she can not think of how to do it, can you help her to solve this problem?
 

Input
Input some groups of test data ,each test data the first number is an integer m (1 <= m <100000), means that the number of operation to do. The next m lines, each line will be an integer p at the beginning, p which has three values:
If p is 0, then there will be an integer e (0 <e <100000), means press element e into Container.

If p is 1, then there will be an integer e (0 <e <100000), indicated that delete the element e from the container  

If p is 2, then there will be two integers a and k (0 <a <100000, 0 <k <10000),means the inquiries, the element is greater than a, and the k-th larger number.
 

Output
For each deletion, if you want to delete the element which does not exist, the output "No Elment!". For each query, output the suitable answers in line .if the number does not exist, the output "Not Find!".
 

Sample Input
  
  
5 0 5 1 2 0 6 2 3 2 2 8 1 7 0 2 0 2 0 4 2 1 1 2 1 2 2 1 3 2 1 4
 

Sample Output
  
  
No Elment! 6 Not Find! 2 2 4 Not Find!
 

Source
 

Recommend
gaojie   |   We have carefully selected several similar problems for you:   2846  2838  2845  2851  2850 
 

AC代码:

注:此题涉及求第k大元素,我还不会利用树状数组求第k大元素,因此参考了http://blog.csdn.net/wsniyufang/article/details/6733431,第二份代码才是我自己学会掌握了之后自己写的。

/*
题意:
三种操作
0 x:向容器里加入x;
1 x: 在容器内删除x,不存在x则输出“No Elment”
2 x y:在容器中找到大于x的第y个数,没有则输出“Not Find”
题解: 树状数组
操作1:直接add(x,1)
操作2:查找sum(x)和sum(x-1),差值为0则不存在x,反之,add(x,-1)即可删除一个x
操作3:首先查找小于等于x的个数s,则找到大于x的第y个数相当于找到第s+y小数
*/
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<cstdio>
using namespace std ;

const int maxn = 100005 ;

struct bit{
     int c[maxn] ; 
     void init(){
          memset(c , 0 ,sizeof(c));
     }
     int lowbit(int x){
         return x&(-x);
     }
     void add(int x ,int d){ //在x处加上d
          for( ; x < maxn ; x+=lowbit(x)) c[x]+=d ; 
     }
     int sum(int x){ //求小于等于x的个数
          int ans = 0 ;
          for( ; x>0 ; x-=lowbit(x))  ans +=c[x] ; 
          return ans ;
     }
     int getkth1(int k){// 求第K小数模版1
          int ans = 0 , cnt = 0 , i ;
          for(i = 20 ; i>=0 ; --i){
                ans += 1<<i ;
                if(ans>=maxn||cnt+c[ans]>=k) ans-=1<<i ;
                else cnt +=c[ans] ;      
          }
          return ans+1 ; 
     }
	 
		int getkth2(int k){<strong>//求第K小数模版2</strong>
			int l=0,r=maxn,mid,f;
			while(l<r-1)
			{ mid=(l+r)>>1;
			  f=sum(mid);
				if(f>=k) r=mid;
				else l=mid;
			}
			return r;
		}
};

int main()
{
	bit my;
	int op,m,x,y;
	while(scanf("%d",&m)!=EOF)
	{
		my.init();
		while(m--)
		{
			scanf("%d%d",&op,&x);
			if(op==0)
			{
				my.add(x,1);
			}
			else if(op==1)
			{
				if(my.sum(x)-my.sum(x-1)==0)
				puts("No Elment!");
				else 
				my.add(x,-1);
			}
			else 
			{
				scanf("%d",&y);
				if(my.sum(maxn-1)-my.sum(x)<y)
				puts("Not Find!");
				else 
				{
					printf("%d\n",my.getkth2(y+my.sum(x)));
				}
			}
		}
	}
    return 0 ;
}








My AC code:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
#include<cmath>
using namespace std;
const int MAX=100010;
int c[MAX+1];
int lowbit(int p)
{
	return p&(-p);
}
int sum(int p)
{
	int s=0;
	while(p)
	{
		s+=c[p];
	    p-=lowbit(p);
	}
	return s;
}
void up(int p,int k)
{
	while(p<=MAX)
	{
		c[p]+=k;
		p+=lowbit(p);
	}
}
int getp(int k)
{
	int l=0,r=MAX,mid,s;
	while(l<r-1)
	{
		mid=(l+r)>>1;
		s=sum(mid);
		if(s>=k)
		{
			r=mid;
		 } 
		 else
		 {
		 	l=mid;
		 }
	}
	return r;
}
int main()
{
	int m,p,e,a,k,ans;
	while(~scanf("%d",&m))
	{
		memset(c,0,sizeof(c));
		while(m--)
		{
			scanf("%d",&p);
			if(p==0)
			{
				scanf("%d",&e);
				up(e,1);
			}
			else if(p==1)
			{
				scanf("%d",&e);
				if(sum(e)-sum(e-1)==0)
				{
					printf("No Elment!\n");
				}
				else
				{
					up(e,-1);
				}
			}
			else
			{
				scanf("%d%d",&a,&k);
				if(sum(MAX)-sum(a)<k)
				{
					printf("Not Find!\n");
				}
				else
				{
					ans=getp(sum(a)+k);
					printf("%d\n",ans);
				}
			}
		}
	}
	return 0;
 } 














  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林下的码路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值