zoukankan      html  css  js  c++  java
  • 【HDU6345】子串查询【前缀和】【线段树】

    题目大意:

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6345
    求给定串llrr的位置里字典序最小的字串出现的次数。


    思路:

    字典序最小的串,肯定是一个字符啊。
    可以用线段树维护一下。时间复杂度O(Tq logn)O(Tq\ logn)
    当然也可以用前缀和。时间复杂度O(t(q+n))O(t(q+n))


    代码:

    线段树:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define N 1000100
    using namespace std;
    
    int n,t,m;
    char c[N];
    
    struct node
    {
    	int l,r,sum;
    	char c;
    }tree[N*3];
    
    void make(int x)  //建树
    {
    	if (tree[x].l==tree[x].r) 
    	{
    		tree[x].c=c[tree[x].l];
    		tree[x].sum=1;
    		return;
    	}
    	int mid=(tree[x].l+tree[x].r)/2;
    	tree[x*2].l=tree[x].l;
    	tree[x*2].r=mid;
    	tree[x*2+1].l=mid+1;
    	tree[x*2+1].r=tree[x].r;
    	make(x*2);
    	make(x*2+1);
    	if (tree[x*2].c==tree[x*2+1].c)  //最小字符和出现次数更改
    	{
    		tree[x].c=tree[x*2].c;
    		tree[x].sum=tree[x*2].sum+tree[x*2+1].sum;
    	}
    	else if (tree[x*2].c<tree[x*2+1].c)
    	{
    		tree[x].c=tree[x*2].c;
    		tree[x].sum=tree[x*2].sum;
    	}
    	else
    	{
    		tree[x].c=tree[x*2+1].c;
    		tree[x].sum=tree[x*2+1].sum;
    	}
    	return;
    }
    
    int find(int x,int l,int r)
    {
    	if (tree[x].l==l&&tree[x].r==r)
    	 return tree[x].sum*100+(int)(tree[x].c-'A');
    	//这里用到了一些小技巧,本来要返回一个字符和出现次数的,但是我直接返回出现次数*100再加上字符的ASCII码值-A的ASCII码值
    	if (tree[x].l==tree[x].r) 
    	 return 0;
    	int mid=(tree[x].l+tree[x].r)/2;
    	if (r<=mid) return find(x*2,l,r);
    	if (l>mid) return find(x*2+1,l,r);
    	int a=find(x*2,l,mid);
    	int b=find(x*2+1,mid+1,r);
    	if (a%100<b%100) return a;
    	if (a%100>b%100) return b;  //取出字符和ASCII码
    	return (a/100+b/100)*100+a%100;  //更新
    }
    
    int main()
    {
    	scanf("%d",&t);
    	int x,y;
    	for (int q=1;q<=t;q++)
    	{
    		scanf("%d%d",&n,&m);
    		cin>>c+1;
    		tree[1].l=1;
    		tree[1].r=n;
    		make(1);
    		printf("Case #%d:\n",q);
    		while (m--)
    		{
    			scanf("%d%d",&x,&y);
    			int a=find(1,x,y);
    		    printf("%d\n",a/100);
    		}
    	}
    	return 0;
    }
    

    前缀和:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #define N 1000100
    using namespace std;
    
    int s[N][30],t,n,m,l,r;
    char c[N];
    
    int main()
    {
    	scanf("%d",&t);
    	for (int q=1;q<=t;q++)
    	{
    		memset(s,0,sizeof(s));
    		scanf("%d%d",&n,&m);
    		cin>>c+1;
    		for (int i=1;i<=n;i++)
    		 s[i][c[i]-'A'+1]++;
    		for (int i=1;i<=n;i++)
    		 for (int j=1;j<=26;j++)
    		  s[i][j]+=s[i-1][j];
    		printf("Case #%d:\n",q);
    		while (m--)
    		{
    			scanf("%d%d",&l,&r);
    			for (int i=1;i<=26;i++)
    			 if (s[r][i]-s[l-1][i])
    			 {
    			 	printf("%d\n",s[r][i]-s[l-1][i]);
    			 	break;
    			 }
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    登入界面的创建
    什么是IO流 以及文件输入输出
    java 的面向对象
    Mac 终端命令大全
    jQuery 的属性
    商城管理系统
    Java IO学习第二天部分详解
    Java IO学习第一天部分详解
    用JAVA描述一个车与修车厂两个事物
    JAVA基础(数组)数组排序和查找数组中是否还有某一个数
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998528.html
Copyright © 2011-2022 走看看