• CODE FESTIVAL 2016 qual B题解


    传送门

    (A)

    什么玩意儿……

    const char t[]={"0CODEFESTIVAL2016"};
    char s[25];int res;
    int main(){
    	scanf("%s",s+1);
    	fp(i,1,16)res+=s[i]!=t[i];
    	printf("%d
    ",res);
    	return 0;
    }
    

    (B)

    什么玩意儿……

    const int N=1e5+5;
    char s[N];int a,b,n,c,cc;
    int main(){
    	scanf("%d%d%d%s",&n,&a,&b,s+1),a+=b;
    	fp(i,1,n){
    		switch(s[i]){
    			case 'c':puts("No");break;
    			case 'a':puts(c+1<=a?(++c,"Yes"):"No");break;
    			case 'b':puts(c+1<=a&&cc+1<=b?(++c,++cc,"Yes"):"No");break;
    		}
    	}
    	return 0;
    }
    

    (C)

    显然需要连成一棵树,且贪心选取边来连接,如果当前连的边是左右连接的,且上下连接的边总共连了(c)条,那么说明每一列只有(m+1-c)个连通块了,那么当前边只需要连这么多条

    //quming
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    typedef long long ll;
    const int N=5e5+5;
    ll res;int a[N],op[N],id[N],top,n,m,c,d;
    inline bool cmp(const int &x,const int &y){return a[x]<a[y];}
    int main(){
    	scanf("%d%d",&n,&m);
    	fp(i,1,n)++top,scanf("%d",&a[top]),op[top]=0,id[top]=top;
    	fp(i,1,m)++top,scanf("%d",&a[top]),op[top]=1,id[top]=top;
    	sort(id+1,id+1+top,cmp);
    	fp(i,1,top){
    //		printf("%d %d %d
    ",id[i],a[id[i]],op[id[i]]);
    		if(!op[id[i]])res+=1ll*a[id[i]]*(m+1-d),++c;
    			else res+=1ll*a[id[i]]*(n+1-c),++d;
    	}
    	printf("%lld
    ",res);
    	return 0;
    }
    

    (D)

    还是贪心,一个贪心是先处理完前面再处理完后面,一个贪心是对于每一个点选择可以卖给他的价格最小的物品卖,记前(i-1)个人中剩余钱数最多的人钱数为(mn),那么卖给第(i)个人的商品价格就是(mn+1),如果(a_i=mn+1)就一个都买不了,并且(++mn),否则我们贪心卖到至少还有一元钱剩余就行了

    然而有一种情况是第(i)个人还剩下恰好(mn+1)元,根据贪心期间肯定是不让(mn)增加最优,那么我们肯定可以在之前得到某一次卖的商品价格(+1),这样就不会令(mn)增加了

    //quming
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    typedef long long ll;
    const int N=5e5+5,inf=0x3f3f3f3f;
    ll res;int a[N],n,mn;
    int main(){
    	scanf("%d",&n);
    	fp(i,1,n)scanf("%d",&a[i]);
    	res=a[1]-1,mn=1;
    	fp(i,2,n){
    		if(a[i]==mn+1)++mn;
    		else res+=(a[i]-1)/(mn+1);
    	}
    	printf("%lld
    ",res);
    	return 0;
    }
    

    (E)

    首先考虑一个暴力的想法,先把所有的串扔到(trie)树里,然后对于询问直接在(trie)树上匹配这个串,同时把所有字典序小于当前转移的子树里的串的个数加入答案

    这样显然要挂掉,而且我们也不可能(26!)枚举所有字母的大小

    (i,j)为两个不同的转移,考虑到(i)这个转移会对(j)的子树造成贡献,当且仅当重定义之后的字母中(i<j),也就是说会对答案造成影响的总共只有(26 imes 26)种状态

    那么我们对于(trie)树上的每一个节点,记录一个(cnt[p][i]),表示当处于节点(p),且状态为(i)(i)表示一种大小关系,假设它表示(a<b),也就是说(a)这个字母字典序比(b)小),此时按照暴力匹配之后的贡献是多少,即从根节点走到(p)的过程中如果转移是(b)就加上(a)那棵子树的(size),那么(cnt[p][i])表示那些(size)的和

    这样对于一个询问,直接枚举所有的大小关系并加上对应的贡献即可

    复杂度(O((n+q)26^2))

    具体细节可以参考代码

    //quming
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    const int N=5e5+5,M=676;
    char t[N];int sz[N],size[N],pos[N],fa[N],ch[N][26];
    int id[N],bg[N],len[N],pi[26],n,q,nd;
    vector<int>cnt[N];
    void ins(R int ID,R int len){
    	R int p=0;
    	for(R int i=1,c;i<=len;++i){
    		c=t[i]-'a';
    		if(!ch[p][c])ch[p][c]=++nd;
    		p=ch[p][c],++sz[p];
    	}
    	id[p]=ID,pos[ID]=p;
    }
    void dfs(int p,int ga,int s){
    	fa[p]=ga;if(ga==-1)cnt[p].resize(M),fa[p]=p;
    	if(id[p])++s,size[id[p]]=s;
    	R int cp=0;fp(i,0,25)cp+=(ch[p][i]!=0);
    	ga=fa[p];if(cp>1)ga=-1;
    	fp(i,0,25)if(ch[p][i])dfs(ch[p][i],ga,s);
    }
    void dd(int p,int ga){
    	if(p&&fa[p]==p)fp(i,0,M-1)cnt[p][i]+=cnt[ga][i];
    	fp(i,0,25)if(ch[p][i])fp(j,i+1,25)if(ch[p][j]){
    		cnt[ch[p][i]][j*26+i]+=sz[ch[p][j]];
    		cnt[ch[p][j]][i*26+j]+=sz[ch[p][i]];
    	}
    	fp(i,0,25)if(ch[p][i])dd(ch[p][i],fa[p]);
    }
    int solve(int k){
    	R int res=size[k];
    	fp(i,0,25)fp(j,i+1,25)res+=cnt[fa[pos[k]]][pi[i]*26+pi[j]];
    	return res;
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
    	scanf("%d",&n);
    	fp(i,1,n)scanf("%s",t+1),len[i]=strlen(t+1),ins(i,len[i]);
    	dfs(0,-1,0);dd(0,-1);
    	scanf("%d",&q);
    	for(R int k;q;--q){
    		scanf("%d%s",&k,t+1);
    		fp(i,1,26)pi[i-1]=t[i]-'a';
    		printf("%d
    ",solve(k));
    	}
    	return 0;
    }
    
  • 相关阅读:
    zeromq学习记录(五)vc下多线程
    zeromq学习记录(七)订阅发布消息封装
    Mozilla研究—从输入URL到显示内容的基本过程
    Mozilla研究—深入理解mozilla所需的背景知识
    Mozilla研究—组件加载机制
    Mozilla研究—传输协议
    Mozilla研究—mozilla中的设计亮点
    GTK+主循环(main loop)的工作原理
    Mozilla研究—mozilla能为我们做什么
    Mozilla研究—组件的创建过程
  • 原文地址:https://www.cnblogs.com/yuanquming/p/11475730.html
Copyright © 2020-2023  润新知