nowcoder - Practice 16

  • A. Lexicographically largest subsequence

  • Given a string s containing only lowercase letters, request the lexicographically largest subsequence.

  • Two ways.

  • 1. Search from 'z' to 'a', start searching for this letter from the current position, add the searched result to the end of the constructed subsequence, and then continue to search from the last position of the searched letter. . until the location is searched.

  • 2. Reverse the entire string and construct a non-descending subsequence with the fastest rising speed from scratch.

    #include"stdio.h"
    #include"string.h"
    char s[105000];
    char a[105000];
    int main(){
    	int i,l,x,now;
    	scanf("%s",s);
    	l=strlen(s);
    	now=97;
    	x=0;
     	for (i=l-1;i>=0;i--){
         if (s[i]>=now) {
         	a[x]=s[i];
         	x++;
         	now=s[i];
         }
    	}
    	for (i=x-1;i>=0;i--) printf("%c",a[i]);
    	printf("\n");
    }
    
    

  • B. beautiful tree

  • There are n trees on the street, numbered 1...n, and the height of the ith tree is ai. define that n trees are beautiful if and only if

    1. For all i, ai=a(n-i+1);

    2. For 1 <= i < n / 2 (not divisible), ai + 1= ai + 1.

  • Due to the limitation of the tree height of this question, the limit case does not exceed 100,000. In order to make the tree height positive, we add 100,000 to all trees, that is, all tree heights do not exceed 200,000 and are greater than 0. After this, we can find that for each tree, they belong to a unique category, that is, when the first tree is k, the tree is beautiful. So classify each number and find the largest class. The answer is n - the size of the largest class.

    
    #include"stdio.h"
    #include"string.h"
    #include"vector"
    using namespace std;
    int  v[505000];
    int  a[505000];
    int main(){
    	int n,i;
    	scanf("%d",&n);
    	for (i=1;i<=n;i++) {scanf("%d",&a[i]);a[i]+=100000;}
    	memset(v,0,sizeof(v));
    	for (i=1;i<=(n+1)/2;i++) {
    		if (a[i]-i+1>0) v[a[i]-i+1]++;
    	}
    	for (i=(n+1)/2+1;i<=n;i++) {
    		if (a[i]-(n-i)>0) v[a[i]-(n-i)]++;
    	}
    	int ans=0;
    	for (i=1;i<=500000;i++) if (v[i]>ans) ans=v[i];
    	printf("%d\n",n-ans);
    }
    

  • C. any point

  • There are several points on the plane. From each point, you can walk in any direction, until you hit another point, and then you can change the direction. How many points need to be added at least so that the point pairs can reach each other.

  • Very powerful question, I didn't expect it to be a combination check at all.

    We classify the given points and divide them into pieces. Any two points within the block can be reached. It can be found that if the abscissa or ordinate of two points are the same, then they must be a block. Then, find the number of blocks. At this point, we add a point to connect the two blocks. Of course, adding one point can also connect up to two points. ans=Number of blocks-1.

    
    #include"stdio.h"
    #include"string.h"
    int x[105];
    int y[105];
    int force 105;
    int father[105];
    int getfather(int k){
    	if (k==father[k]) return k;
    	else father[k]= getfather(father[k]);
    	return father[k];
    }
    int main(){
    	int n,i,j,a,b,ans;
    	years=0;
    	scanf("%d",&n);
    	
    	for (i=1;i<=n;i++) father[i]=i;
        for (i=1;i<=n;i++) scanf("%d %d",&x[i],&y[i]);
        for (i=1;i<=n;i++)
        for (j=i+1;j<=n;j++)
        if (x[i]==x[j]||y[i]==y[j]) {
        	a=getfather(i);
        	b=getfather(j);
        	father[b]=a;
        }
        for (i=1;i<=n;i++) father[i]=getfather(father[i]);
        memset(vis,0,sizeof(vis));
        for (i=1;i<=n;i++) if (vis[father[i]]==0){
        	vis[father[i]]=1;
        	years++;
        }
        printf("%d\n",ans-1);
    }
    

  • E. Evaluation

  • Given n numbers a1, a2, ..., an. Define f(l, r) = al | al+1| ... | ar. Now enumerate (1 <= l <= r <= n) and ask how many different f values ​​there are.

  • Uh. . Tell me about my tle's practice.

    First the segment tree is processed from the OR and sum of [l, r]. Multipliers are processed for each position. Then enumerate each position from 1 to n. Try to multiply the maximum amount from the current position. If the OR and sum of the position reached after the multiplication is unchanged, skip directly. Otherwise, the length of the two-point jump, that is, the distance of the first jump, is not the same as the or sum of continuing to try to reach that point. If unchanged, skip, otherwise continue iteration. Until, jump forward one position. The complexity is about O(n(logn)^2). And then the glorious T.

  • The correct way is as follows.

    Since the number does not exceed 2^20. In other words, the number of jumps back in each position is no more than 20 times. So we just need to preprocess each bit of OR at the current position, at which points will be changed first. After processing this, sort by point, and then start from the first point or, or a position, and add it to the set. Finally output the size of the set.

    So now the problem is, how to quickly preprocess out, at which point will be changed first for each bit of OR in the current position. It can be reversed from back to front. If it is 1, follow the new one, otherwise, get it from the back.

    #include"stdio.h"
    #include"string.h"
    #include"set"
    #include"algorithm"
    #define maxn 105000
    using namespace std;
    set<int>s;
    int a[maxn][21];
    int b[maxn];
    int sign[50];
    struct node{
    	int wei, sum;
    }xu[50];
    int cmp1(node a,node b){
    	return a.sum<b.sum;
    }
    int main(){
    	int i,n,x,now,l,j;
    	int ff=0;
    	scanf("%d",&n);
    	for (i=1;i<=n;i++) scanf("%d",&b[i]);
    	memset(a,-1,sizeof(a));
    	
    	for (i=n;i>=1;i--){
    		l=0;
    		x=b[i];
    		if (b[i]==0) ff=1;
    		memset(sign,0,sizeof(sign));
    		while(x>0){
    			l++;
    			sign[l]=x%2;
    			x=x/2;
    		}
    		for (j=1;j<=20;j++)
    		if (sign[j]==1) a[i][j]=i;
    	         	   else a[i][j]=a[i+1][j];
    	}
    	s.clear();/*
    	for (i=1;i<=n;i++){
    		for (j=1;j<=20;j++) printf("%5d",a[i][j]);
    		printf("\n");
    	}*/
    	for(i=1;i<=n;i++) {
    		now=b[i];
    		for (j=1;j<=20;j++) {
    			xu[j].wei=j;
    			xu[j].sum=a[i][j];
    		}
    		sort(xu+1,xu+1+20,cmp1);
    		xu[21].sum=-1;
    		for (j=1;j<=20;j++) if (xu[j].sum!=-1) {
    			if (xu[j].sum!=xu[j+1].sum){
    			now=now|(1<<(xu[j].wei-1));
    			s.insert(now);
    		    }else {
    		    	now=now|(1<<(xu[j].wei-1));
    		    }
    		}
    	}
    	printf("%d\n",s.size()+ff);
    }
    

  • F. Selection value

  • Given n numbers, select three numbers from them so that the value of the largest minus the smallest is less than or equal to d, and ask how many options are there.

  • The ruler can be taken.

    
    #include"stdio.h"
    long long a[105000];
    int main(){
    	long long n,m,i;
    	scanf("%lld %lld",&n,&m);
    	for (i=1;i<=n;i++) scanf("%lld",&a[i]);
    	long long r=1;
    	long long ans=0;
    	for (i=1;i<=n;i++){
    		while(r<=n&&a[r]-a[i]<=m) r++;
    		if (r-1-i>=2) ans+=(r-1-i)*(r-1-i-1)/2;
    	}
    	printf("%lld\n",ans);
    }
    

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325303437&siteId=291194637