zoukankan      html  css  js  c++  java
  • 【洛谷5335】[THUSC2016] 补退选(指针实现Trie)

    点此看题面

    大致题意: 三种操作:加入一个字符串,删除一个字符串,求最早什么时候以某个字符串为前缀的字符串个数超过给定值。

    (Trie)

    这道题显然是(Trie)的暴力裸题。

    考虑我们对于(Trie)上的每个节点,开一个(vector),其中第(i)位(注意(vector)的下标是从(0)开始的)存储以这个节点所代表的字符串为前缀的字符串个数超过(i)的最早时间。

    至于这怎么维护,只要同时再维护一下对于每个字符串当前以其为前缀的字符串个数,由于这个个数每次最多修改(1),因此我们只要在每次修改时比较个数与(vector)(size),若个数超过了(vector)(size),就在(vector)(push\_back)当前时间。

    询问时只要找到对应节点,如果(vector)(size)大于询问的给定值(v),就返回(vector)的第(v)位,否则返回(-1)

    关于内存

    一开始,我很自信的把数组开到了(10^5*60),又由于没看见题目中说只有前十个小写字母,所以就完美地(MLE)了......

    然后想了想发现(Trie)的数组是显然用不满的,但究竟该开多大呢?

    思索半天没有结果,一狠心便去学了发指针实现(Trie),然后写完调了调(bug),就过了此题。

    看看此时内存,仅有(40.58MB),真是无语......

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    #define K 60
    using namespace std;
    class FastIO
    {
    	private:
    		#define FS 100000
    		#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
    		#define pc(c) (C==E&&(clear(),0),*C++=c)
    		#define tn (x<<3)+(x<<1)
    		#define D isdigit(c=tc())
    		int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
    	public:
    		I FastIO() {A=B=FI,C=FO,E=FO+FS;}
    		Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
    		Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    		I void reads(string& x) {x="";W(isspace(c=tc()));W(x+=c,!isspace(c=tc())&&~c);}
    		Tp I void write(Ty x) {x<0&&(pc('-'),x=-x);W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
    		Tp I void writeln(Con Ty& x) {write(x),pc('
    ');}
    		I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
    }F;
    class Trie//指针实现Trie
    {
    	private:
    		struct node
    		{
    			int V;node *S[10];vector<int> P;
    			I node() {V=0,P.clear();for(RI i=0;i^10;++i) S[i]=NULL;}//初始化清空节点,一定要写,不然会挂
    		}*rt;
    	public:
    		I Trie() {rt=new node;}//初始化根节点
    		I void Upt(Con string& s,CI v,CI ti)//修改(插入/删除)
    		{
    			node *x=rt;for(RI i=0,l=s.length(),t;i^l;++i)
    				x->S[t=s[i]-97]==NULL&&(x->S[t]=new node),x=x->S[t],//如果子节点为空,新建子节点
    				(x->V+=v)>x->P.size()&&(x->P.push_back(ti),0);//更新vector
    		}
    		I int Qry(Con string& s,CI v)//询问
    		{
    			node *x=rt;for(RI i=0,l=s.length(),t;i^l;++i)
    				if(x->S[t=s[i]-97]==NULL) return -1;else x=x->S[t];//如果子节点为空,直接返回-1
    			return x->P.size()>v?x->P[v]:-1;//判断是否有解,有解则返回答案,否则返回-1
    		}
    }T;
    int main()
    {
    	RI Qt,i,op,x,y,z,lst=0;string s;for(F.read(Qt),i=1;i<=Qt;++i) switch(F.read(op),op)
    	{
    		case 1:F.reads(s),T.Upt(s,1,i);break;
    		case 2:F.reads(s),T.Upt(s,-1,i);break;
    		case 3:F.reads(s),F.read(x,y,z),F.writeln(lst=T.Qry(s,(1LL*x*abs(lst)+y)%z));break;//注意1LL,我原本没写就挂成了60分
    	}return F.clear(),0;
    }
    
  • 相关阅读:
    Analysis Services 查询性能十大最佳实践(转)
    谈谈一年来对“数据仓库”概念的困惑、探索和感悟(转)
    用sql语句添加删除主键
    大文件流操作及编码
    SQL Server CONVERT() 函数
    正则表达式提取案例1
    解析SQL SERVER存储过程返回值
    文件操作类Path
    HTTP状态码
    自己写的遮罩层效果
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu5335.html
Copyright © 2011-2022 走看看