• BZOJ 3439 Kpm的MCpassword Trie树+可持久化线段树


    题目大意:给定n个字符串,对于每一个字符串求以这个字符串为后缀的字符串中第k小的编号

    首先将字符串反转 那么就变成了对于每一个字符串求以这个字符串为前缀的字符串中第k小的编号

    然后考虑对字符串排序 那么对于每一个字符串以它为前缀的字符串一定是连续的 那么就转化成了区间第k小 这个用可持久化线段树能够解决

    排序自然不能直接排 既然是字符串 考虑Trie树+DFS就可以 注意字符串有反复的 小心

    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define M 100100
    using namespace std;
    struct Trie{
    	vector<int> num;
    	Trie *son[26];
    	void* operator new (size_t size);
    }*root,*mempool,*C;
    struct Segtree{
    	Segtree *ls,*rs;
    	int num;
    	void* operator new (size_t size,Segtree *_,Segtree *__,int ___);
    }*tree[M],*_mempool,*G;
    int n,a[M],l[M],r[M],tot;
    char s[M];
    void* Trie :: operator new (size_t size)
    {
    	if(C==mempool)
    	{
    		C=new Trie[1<<15];
    		mempool=C+(1<<15);
    		memset(C,0,sizeof(Trie)*(1<<15) );
    	}
    	return C++;
    }
    void* Segtree :: operator new (size_t size,Segtree *_,Segtree *__,int ___)
    {
    	if(G==_mempool)
    	{
    		G=new Segtree[1<<15];
    		_mempool=G+(1<<15);
    		memset(G,0,sizeof(Segtree)*(1<<15) );
    	}
    	G->ls=_;
    	G->rs=__;
    	G->num=___;
    	return G++;
    }
    void Insert(Trie*&p,char *str,int pos)
    {
    	if(!p) p=new Trie;
    	if(!*str)
    	{
    		p->num.push_back(pos);
    		return ;
    	}
    	Insert(p->son[(*str)-'a'],str+1,pos);
    }
    void DFS(Trie *p)
    {
    	int i;
    	vector<int>::iterator it;
    	p->num.begin();
    	int temp=tot+1;
    	for(it=p->num.begin();it!=p->num.end();it++)
    	{
    		a[++tot]=*it;
    		l[*it]=temp;
    	}
    	for(i=0;i<26;i++)
    		if(p->son[i])
    			DFS(p->son[i]);
    	for(it=p->num.begin();it!=p->num.end();it++)
    		r[*it]=tot;
    }
    Segtree* Build_Tree(Segtree *p,int x,int y,int val)
    {
    	int mid=x+y>>1;
    	if(x==y) return new (0x0,0x0,p->num+1) Segtree;
    	if(val<=mid) return new (Build_Tree(p->ls,x,mid,val),p->rs,p->num+1) Segtree;
    	else 		 return new (p->ls,Build_Tree(p->rs,mid+1,y,val),p->num+1) Segtree; 
    }
    int Get_Ans(Segtree *p1,Segtree *p2,int x,int y,int k)
    {
    	int mid=x+y>>1;
    	if(x==y) return mid;
    	int temp=p2->ls->num-p1->ls->num;
    	if(k<=temp) return Get_Ans(p1->ls,p2->ls,x,mid,k);
    	else return Get_Ans(p1->rs,p2->rs,mid+1,y,k-temp);
    }
    int main()
    {
    	int i,j,k;
    	cin>>n;
    	for(i=1;i<=n;i++)
    	{
    		scanf("%s",s+1);
    		int temp=strlen(s+1);
    		for(j=1;j<<1<=temp;j++)
    			swap(s[j],s[temp+1-j]);
    		Insert(root,s+1,i);
    	}
    	DFS(root);
    	tree[0]=new (0x0,0x0,0) Segtree;
    	tree[0]->ls=tree[0]->rs=tree[0];
    	for(i=1;i<=n;i++)
    		tree[i]=Build_Tree(tree[i-1],1,n,a[i]);
    	for(i=1;i<=n;i++)
    	{
    		scanf("%d",&k);
    		if(k>r[i]-l[i]+1) puts("-1");
    		else printf("%d
    ", Get_Ans(tree[l[i]-1],tree[r[i]],1,n,k) );
    	}
    }
    


  • 相关阅读:
    Session_End引发的性能问题!
    可能引发性能问题的几个写法,看看你占哪一个.
    优化你的DiscuzNT3.0,让它跑起来(2)发帖回帖篇
    什么是经济学
    生产可能性边界和机会成本
    九宫格的实现(转)
    LAMP的安装和配置
    iPhone 开发过程中的一些小技术的总结(转)
    有效的利用资源边际成本与边际利益
    Dijkstra算法(注:单源最短路径的贪心算法)和数学归纳法<转>
  • 原文地址:https://www.cnblogs.com/clnchanpin/p/6893547.html
Copyright © 2020-2023  润新知