zoukankan      html  css  js  c++  java
  • 省选测试35

    总结

    名次和昨天还是一样,不过状态有所提升

    A.事情的相似度

    分析

    对于字符串建立后缀自动机

    那么区间 ([l,r]) 的答案就是区间中任意两个点贡献的最大值

    对于后缀树上的每一个节点开一个 (set) 维护 (endpos) 集合

    将子树内的点所在的 (set) 启发式合并,并在 (lca) 处计算能够贡献答案的点对

    发现一个点和它的前驱后继贡献答案一定是最优的

    这样最终点对的数量是 (nlogn) 级别的

    把所有的点对和询问按照右端点从小到大排序依次计算

    只要拿树状数组维护后缀最大值即可

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<set>
    #define rg register
    inline int read(){
    	rg int x=0,fh=1;
    	rg char ch=getchar();
    	while(ch<'0' || ch>'9'){
    		if(ch=='-') fh=-1;
    		ch=getchar();
    	}
    	while(ch>='0' && ch<='9'){
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return x*fh;
    }
    const int maxn=4e5+5;
    int n,q,ans[maxn],shuyu[maxn],tp;
    char s[maxn];
    struct jie{
    	int l,r,id;
    	friend bool operator < (const jie& A,const jie& B){
    		return A.r<B.r;
    	}
    }c[maxn];
    struct Node{
    	int l,r,val;
    	Node(){}
    	Node(rg int aa,rg int bb,rg int cc){
    		l=aa,r=bb,val=cc;
    	}
    	friend bool operator < (const Node& A,const Node& B){
    		return A.r<B.r;
    	}
    }sta[maxn*20];
    std::set<int> se[maxn];
    #define sit std::set<int>::iterator
    struct SAM{
    	int fa[maxn],len[maxn],ch[maxn][5],lst,cnt,h[maxn],tot;
    	struct asd{
    		int to,nxt;
    	}b[maxn];
    	void ad(rg int aa,rg int bb){
    		b[tot].to=bb;
    		b[tot].nxt=h[aa];
    		h[aa]=tot++;
    	}
    	void insert(rg int c){
    		rg int p=lst;
    		rg int np=lst=++cnt;
    		len[np]=len[p]+1;
    		for(;p && !ch[p][c];p=fa[p]) ch[p][c]=np;
    		if(!p) fa[np]=1;
    		else {
    			rg int q=ch[p][c];
    			if(len[q]==len[p]+1) fa[np]=q;
    			else {
    				rg int nq=++cnt;
    				len[nq]=len[p]+1;
    				memcpy(ch[nq],ch[q],sizeof(ch[q]));
    				fa[nq]=fa[q];
    				fa[np]=fa[q]=nq;
    				for(;p && ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
    			}
    		}
    	}
    	void build(){
    		lst=cnt=1;
    		for(rg int i=1;i<=n;i++){
    			insert(s[i]-'0');
    			se[lst].insert(i);
    		}
    	}
    	void dfs(rg int now){
    		rg sit it1,it2;
    		for(rg int i=h[now];i!=-1;i=b[i].nxt){
    			rg int u=b[i].to;
    			if(u==fa[now]) continue;
    			dfs(u);
    			if(se[now].size()<se[u].size()) std::swap(se[now],se[u]);
    			for(rg sit it=se[u].begin();it!=se[u].end();++it){
    				rg int tmp=*it;
    				se[now].insert(tmp);
    				if(se[now].size()>1){
    					it1=it2=se[now].lower_bound(tmp);
    					++it2;
    					if(it1==se[now].begin()){
    						sta[++tp]=Node(tmp,*it2,len[now]);
    					} else if(it2==se[now].end()){
    						--it1;
    						sta[++tp]=Node(*it1,tmp,len[now]);
    					} else {
    						sta[++tp]=Node(tmp,*it2,len[now]);
    						--it1;
    						sta[++tp]=Node(*it1,tmp,len[now]);
    					}
    				}
    			}
    			for(rg sit it=se[u].begin();it!=se[u].end();++it){
    				se[now].insert(*it);
    			}
    		}
    	}
    	void pre(){
    		memset(h,-1,sizeof(h));
    		tot=1;
    		for(rg int i=2;i<=cnt;i++){
    			ad(i,fa[i]),ad(fa[i],i);
    		}
    		dfs(1);
    		std::sort(sta+1,sta+tp+1);
    	}
    }sam;
    int tr[maxn];
    int lb(rg int xx){
    	return xx&-xx;
    }
    int cx(rg int wz){
    	rg int nans=0;
    	for(rg int i=wz;i<=n;i+=lb(i)) nans=std::max(nans,tr[i]);
    	return nans;
    }
    void xg(rg int wz,rg int val){
    	for(rg int i=wz;i>0;i-=lb(i)) tr[i]=std::max(tr[i],val);
    }
    int main(){
    	n=read(),q=read();
    	scanf("%s",s+1);
    	sam.build();
    	for(rg int i=1;i<=q;i++){
    		c[i].l=read(),c[i].r=read(),c[i].id=i;
    	}
    	std::sort(c+1,c+q+1);
    	sam.pre();
    	rg int now=1,head=1;
    	for(rg int i=1;i<=n;i++){
    		while(now<=tp && sta[now].r==i){
    			xg(sta[now].l,sta[now].val);
    			now++;
    		}
    		while(head<=q && c[head].r==i){
    			ans[c[head].id]=cx(c[head].l);
    			head++;
    		}
    	}
    	for(rg int i=1;i<=q;i++) printf("%d
    ",ans[i]);
    	return 0;
    }
    

    B.跳蚤王国的宰相

    分析

    发现满足条件的点一定是树的重心

    于是我们先求出原树的重心 (C),以之为根后,每个子树的大小都不超过 (frac{n}{2})

    (C) 连出去的边即可,因为拆下来的子树的大小肯定不超过 (frac{n}{2})

    贪心地从大到小拆

    记录一个前缀和二分就行了

    拆到了当前点所在的子树要特判一下

    分为两种情况,一种是强制拆,一种是不拆

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<set>
    #define rg register
    inline int read(){
    	rg int x=0,fh=1;
    	rg char ch=getchar();
    	while(ch<'0' || ch>'9'){
    		if(ch=='-') fh=-1;
    		ch=getchar();
    	}
    	while(ch>='0' && ch<='9'){
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return x*fh;
    }
    const int maxn=1e6+5;
    int h[maxn],tot=1,n;
    struct asd{
    	int to,nxt;
    }b[maxn<<1];
    void ad(rg int aa,rg int bb){
    	b[tot].to=bb;
    	b[tot].nxt=h[aa];
    	h[aa]=tot++;
    }
    int siz[maxn],maxsiz[maxn],rt;
    void getroot(rg int now,rg int lat){
    	siz[now]=1;
    	for(rg int i=h[now];i!=-1;i=b[i].nxt){
    		rg int u=b[i].to;
    		if(u==lat) continue;
    		getroot(u,now);
    		siz[now]+=siz[u];
    		maxsiz[now]=std::max(maxsiz[now],siz[u]);
    	}
    	maxsiz[now]=std::max(maxsiz[now],n-siz[now]);
    	if(maxsiz[now]<maxsiz[rt]) rt=now;
    }
    int shuyu[maxn],sta[maxn],tp,sum[maxn],wz[maxn];
    void dfs(rg int now,rg int lat,rg int col){
    	shuyu[now]=col;
    	siz[now]=1;
    	for(rg int i=h[now];i!=-1;i=b[i].nxt){
    		rg int u=b[i].to;
    		if(u==lat) continue;
    		dfs(u,now,col);
    		siz[now]+=siz[u];
    	}
    }
    int main(){
    	memset(h,-1,sizeof(h));
    	n=read();
    	rg int aa,bb;
    	for(rg int i=1;i<n;i++){
    		aa=read(),bb=read();
    		ad(aa,bb),ad(bb,aa);
    	}
    	maxsiz[0]=0x3f3f3f3f;
    	getroot(1,0);
    	for(rg int i=h[rt];i!=-1;i=b[i].nxt){
    		dfs(b[i].to,rt,b[i].to);
    		sta[++tp]=siz[b[i].to];
    	}
    	std::sort(sta+1,sta+tp+1);
    	std::reverse(sta+1,sta+tp+1);
    	for(rg int i=1;i<=tp;i++) wz[sta[i]]=wz[sta[i]]?wz[sta[i]]:i;
    	for(rg int i=1;i<=tp;i++) sum[i]=sum[i-1]+sta[i];
    	for(rg int i=1;i<=n;i++){
    		if(rt==i) printf("0
    ");
    		else {
    			rg int tmp=siz[shuyu[i]];
    			rg int nans=std::lower_bound(sum+1,sum+tp+1,n-n/2-siz[i])-sum;
    			if(nans>=wz[tmp]){
    				nans=std::min(std::lower_bound(sum+1,sum+tp+1,n-n/2+tmp-siz[i])-sum-1,std::lower_bound(sum+1,sum+tp+1,n-n/2)-sum);
    			}
    			printf("%d
    ",nans);
    		}
    	}
    	return 0;
    }
    

    C.蛐蛐国的修墙方案

    分析

    如果把 (i)(p[i]) 连边,那么最终会形成若干个环

    处理长度为 (2) 的环,每一个环有两种选择

    枚举每一个环是哪一种选择,直接搜索就行

    复杂度为 (n2^{frac{n}{4}})

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<set>
    #include<vector>
    #include<cstdlib>
    #define rg register
    inline int read(){
    	rg int x=0,fh=1;
    	rg char ch=getchar();
    	while(ch<'0' || ch>'9'){
    		if(ch=='-') fh=-1;
    		ch=getchar();
    	}
    	while(ch>='0' && ch<='9'){
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return x*fh;
    }
    const int maxn=405;
    int n,a[maxn],mp[maxn][maxn],vis[maxn],tim,sta[maxn],tp,mat[maxn];
    char s[maxn];
    std::vector<int> g[maxn];
    void predfs(rg int now){
    	vis[now]=tim;
    	g[tim].push_back(now);
    	for(rg int i=1;i<=n;i++){
    		if(mp[now][i] && !vis[i]) predfs(i);
    	}
    }
    bool jud(){
    	rg int sum=0;
    	for(rg int i=1;i<=n;i++){
    		sum+=mat[i];
    		if(sum<0) return 0;
    	}
    	if(sum!=0) return 0;
    	return 1;
    }
    void init(rg int aa,rg int bb){
    	mat[std::min(aa,bb)]=1;
    	mat[std::max(aa,bb)]=-1;
    }
    void init2(rg int aa,rg int bb){
    	if(a[aa]==bb){
    		mat[aa]=1,mat[bb]=-1;
    	} else {
    		mat[aa]=-1,mat[bb]=1;
    	}
    }
    void dfs(rg int now){
    	if(now>tp){
    		if(jud()){
    			for(rg int i=1;i<=n;i++){
    				if(mat[i]<0) s[i]=')';
    				else s[i]='(';
    			}
    			printf("%s
    ",s+1);
    			std::exit(0);
    		}
    		return;
    	}
    	rg int tmp=sta[now],tmp2=g[tmp].size();
    	for(rg int i=0;i<tmp2;i+=2){
    		init2(g[tmp][i],g[tmp][i+1]);
    	}
    	dfs(now+1);
    	for(rg int i=0;i<tmp2;i++) mat[g[tmp][i]]=0;
    	for(rg int i=1;i<tmp2-1;i+=2){	
    		init2(g[tmp][i],g[tmp][i+1]);
    	}
    	init2(g[tmp][0],g[tmp][tmp2-1]);
    	dfs(now+1);
    	for(rg int i=0;i<tmp2;i++) mat[g[tmp][i]]=0;
    }
    int main(){
    	n=read();
    	for(rg int i=1;i<=n;i++){
    		a[i]=read();
    		mp[i][a[i]]=mp[a[i]][i]=1;
    	}
    	for(rg int i=1;i<=n;i++){
    		if(!vis[i]){
    			tim++;
    			predfs(i);
    		}
    	}
    	for(rg int i=1;i<=tim;i++){
    		if(g[i].size()==2){
    			init(g[i][0],g[i][1]);
    		} else {
    			sta[++tp]=i;
    		}
    	}
    	dfs(1);
    	return 0;
    }
    
  • 相关阅读:
    梯度下降
    最小二乘法模型的推导原理
    斗图啦+多线程(队列)
    scrapy错误-[scrapy.core.scraper] ERROR: Spider error processing
    python使用requests时报错requests.exceptions.SSLError: HTTPSConnectionPool
    AttributeError: module 'requests' has no attribute 'get'的错误疑惑
    *arg,**kwargs的参数作用的疑惑
    scrapy框架--新建调试的main.py文件
    Scrapy框架——安装以及新建scrapy文件
    爬虫-ajax请求遇到Unicode编码问题
  • 原文地址:https://www.cnblogs.com/liuchanglc/p/14475474.html
Copyright © 2011-2022 走看看