• 雅礼集训2017day7乱写


    看来(3)的倍数的天数都没有

    t1

    水了一发(SA),然后(WA)

    冷静分析发现我是(sb)

    先搞一个(SAM),两个位置的最长公共后缀长度就是两个位置代表节点的(len[lca])

    我们先把询问离线,按(r)排序,然后扫描数组

    我们发现这个事情其实和树点涂色每次把一条链染上同一种颜色

    如果在(access)过程中某个点已经被染色了,那么说明这个点是某两个位置的(lca),用线段树来维护最大值

    注意保存两个位置时保存在左侧节点

    #include<bits/stdc++.h>
    using namespace std;
    namespace red{
    #define ls(p) (p<<1)
    #define rs(p) (p<<1|1)
    #define mid ((l+r)>>1)
    #define lowbit(i) ((i)&(-i))
    	inline int read()
    	{
    		int x=0;char ch,f=1;
    		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    		if(ch=='-') f=0,ch=getchar();
    		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    		return f?x:-x;
    	}
    	const int N=4e5+10,p=1e9+7;
    	int n,m,tot=1,pre=1;
    	char s[N];
    	int pos[N],ret[N];
    	struct node
    	{
    		int l,r,id;
    		inline bool operator < (const node &t) const
    		{
    			return r<t.r;
    		}
    	}q[N];
    	struct SAM
    	{
    		int fa[N],len[N],endpos[N],son[N][2];
    		inline void insert(int c)
    		{
    			int p=pre,np=pre=++tot;endpos[tot]=1;
    			len[np]=len[p]+1;
    			for(;p&&!son[p][c];p=fa[p]) son[p][c]=np;
    			if(!p) fa[np]=1;
    			else
    			{
    				int q=son[p][c];
    				if(len[q]==len[p]+1) fa[np]=q;
    				else
    				{
    					int nq=++tot;
    					for(int i=0;i<2;++i) son[nq][i]=son[q][i];
    					len[nq]=len[p]+1;
    					fa[nq]=fa[q];
    					fa[q]=fa[np]=nq;
    					for(;p&&son[p][c]==q;p=fa[p]) son[p][c]=nq;
    				}
    			}
    		}
    	}sam;
    	struct SGT
    	{
    		int ans[N<<2];
    		inline void update(int pos,int l,int r,int p,int k)
    		{
    		//	cout<<pos<<' '<<l<<' '<<r<<endl;
    			ans[p]=max(ans[p],k);
    			if(l==r) return;
    			if(pos<=mid) update(pos,l,mid,ls(p),k);
    			else update(pos,mid+1,r,rs(p),k);
    		}
    		inline int query(int tl,int tr,int l,int r,int p)
    		{
    			if(tl<=l&&r<=tr) return ans[p];
    			int ret=0;
    			if(tl<=mid) ret=query(tl,tr,l,mid,ls(p));
    			if(tr>mid) ret=max(ret,query(tl,tr,mid+1,r,rs(p)));
    			return ret;
    		}
    	}tr;
    	struct LCT	
    	{
    		int st[N],f[N],cor[N],son[N][2];
    		inline void pushdown(int x)
    		{
    			if(son[x][0]) cor[son[x][0]]=cor[x];
    			if(son[x][1]) cor[son[x][1]]=cor[x];
    		}
    		inline bool nroot(int x)
    		{
    			return son[f[x]][0]==x||son[f[x]][1]==x;
    		}
    		inline int ident(int x)
    		{
    			return son[f[x]][1]==x;
    		}
    		inline void rotate(int x)
    		{
    			int y=f[x],z=f[y],k=son[y][1]==x,w=son[x][!k];
    			if(nroot(y)) son[z][son[z][1]==y]=x;son[x][!k]=y,son[y][k]=w;
    			if(w) f[w]=y;f[y]=x,f[x]=z;
    		}
    		inline void splay(int x)
    		{
    			int y=x,z=0;
    			st[++z]=y;
    			while(nroot(y)) st[++z]=y=f[y];
    			while(z) pushdown(st[z--]);
    			while(nroot(x))
    			{
    				y=f[x];
    				if(nroot(y)) rotate(ident(x)==ident(y)?y:x);
    				rotate(x);
    			}
    		}
    		inline void access(int x,int c)
    		{
    			for(int y=0;x;x=f[y=x])
    			{
    				splay(x);
    				if(cor[x]) tr.update(cor[x],1,n,1,sam.len[x]);
    				cor[x]=c;
    				son[x][1]=y;
    			}
    		}
    	}lct;
    	inline void main()
    	{
    		n=read(),m=read();
    		scanf("%s",s+1);
    		for(int i=1;i<=n;++i) sam.insert(s[i]-'0'),pos[i]=pre;
    		for(int i=tot;i;--i) lct.f[i]=sam.fa[i];
    		for(int i=1;i<=m;++i) q[i].l=read(),q[i].r=read(),q[i].id=i;
    		sort(q+1,q+m+1);
    		for(int i=1,j=1;i<=n&&j<=m;++i)
    		{
    			lct.access(pos[i],i);
    			for(;j<=m&&q[j].r<=i;++j) ret[q[j].id]=tr.query(q[j].l,i,1,n,1);
    		}
    		for(int i=1;i<=m;++i) printf("%d
    ",ret[i]);
    	}
    }
    signed main()
    {
    	red::main();
    	return 0;
    }
    

    t2

    重心定义没有一个子树大小乘以二超过(n)

    我们发现每个节点至多有一颗子树大小超过要求,而且重心在这颗子树内

    很多细节。。。很难写(呜呜呜)

    #include<bits/stdc++.h>
    using namespace std;
    namespace red{
    #define ls(p) (p<<1)
    #define rs(p) (p<<1|1)
    #define mid ((l+r)>>1)
    #define lowbit(i) ((i)&(-i))
    	inline int read()
    	{
    		int x=0;char ch,f=1;
    		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    		if(ch=='-') f=0,ch=getchar();
    		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    		return f?x:-x;
    	}
    	const int N=1e6+10,p=1e9+7;
    	int n,sum,num;
    	vector<int> eg[N];
    	inline void link(int x,int y)
    	{
    		eg[x].push_back(y);
    		eg[y].push_back(x);
    	}
    	int str[N],mx[N],ans[N],rt;
    	inline bool cmp(int x,int y){return str[x]>str[y];}
    	inline void find(int now,int fa)
    	{
    		str[now]=1;
    		for(auto t:eg[now])
    		{
    			if(t==fa) continue;
    			find(t,now);
    			mx[now]=max(mx[now],str[t]);
    			str[now]+=str[t];
    		}
    		mx[now]=max(mx[now],n-str[now]);
    		if(mx[now]<mx[rt]) rt=now;
    	}
    	inline void dfs(int now,int fa)
    	{
    		str[now]=1;
    		for(auto t:eg[now])
    		{
    			if(t==fa) continue;
    			dfs(t,now);
    			str[now]+=str[t];
    		}
    	}
    	inline void dfs2(int now,int fa,int top)
    	{
    		ans[now]=num+((n-top-str[now])*2>n);
    		for(auto t:eg[now]) 
    			if(t!=fa) dfs2(t,now,top);
    	}
    	inline void main()
    	{
    		n=read();
    		for(int x,y,i=1;i<n;++i)
    		{
    			x=read(),y=read();
    			link(x,y);
    		}
    		mx[0]=p;find(1,0);
    		dfs(rt,0);
    		sort(eg[rt].begin(),eg[rt].end(),cmp);
    		for(auto t:eg[rt])
    		{
    			sum+=str[t];
    			if(sum*2>=n) break;
    			++num;
    		}
    		for(auto t:eg[rt])
    		{
    			dfs2(t,rt,sum-max(str[t],str[eg[rt][num]]));
    		}
    		for(int i=1;i<=n;++i) printf("%d
    ",ans[i]);
    	}
    }
    signed main()
    {
    	red::main();
    	return 0;
    }
    

    我们可以爆搜,复杂度(O(2^{100}))

    我们发现一条边两个端点一定是一个左括号一个右括号,保证有解的话那么必定有偶环,复杂度上界变为

    (O(2^{50}))

    我们发现如果是只有(2)个点环,那么一定是靠左的那个是左括号,可以(O(1))

    最坏情况变成了(4)个点的环,最多有(25)个,复杂度(O(2^{25}))

    好像可做了,爆搜吧qwq

    #include<bits/stdc++.h>
    using namespace std;
    namespace red{
    #define ls(p) (p<<1)
    #define rs(p) (p<<1|1)
    #define mid ((l+r)>>1)
    #define lowbit(i) ((i)&(-i))
    	inline int read()
    	{
    		int x=0;char ch,f=1;
    		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    		if(ch=='-') f=0,ch=getchar();
    		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    		return f?x:-x;
    	}
    	const int N=210,p=1e9+7;
    	int n;
    	vector<int> eg[N];
    	bool vis[N];
    	int cir[N],tot;
    	int c[N][N],b[N];
    	int ans[N];
    	int len[N],num;
    	inline void link(int x,int y)
    	{
    		eg[x].push_back(y);
    		eg[y].push_back(x);
    	}
    	inline void sea(int now,int fa)
    	{
    		if(vis[now]) return;
    		vis[now]=1;
    		cir[tot++]=now;
    		for(auto t:eg[now])
    			if(t!=fa) sea(t,now);
    	}
    	inline void search(int now)
    	{
    		tot=0;
    		sea(now,0);
    		if(tot==2) ans[min(cir[0],cir[1])]=1,ans[max(cir[0],cir[1])]=-1;
    		else
    		{
    			len[++num]=tot;
    			for(int i=0;i<tot;++i)
    				c[num][i]=cir[i],b[cir[i]]=num;
    		}
    	}
    	bool flag;
    	inline void dfs(int now,int sum)
    	{
    		if(sum<0) return;
    		if(now==n+1)
    		{
    			for(int i=1;i<=n;++i)
    				putchar(ans[i]==1?'(':')');
    			flag=1;return;
    		}
    		if(!ans[now])
    		{
    			ans[c[b[now]][0]]=1;
    			for(int i=1;i<=len[b[now]];++i)
    				ans[c[b[now]][i]]=-ans[c[b[now]][i-1]];
    			dfs(now+1,sum+ans[now]);
    			if(flag) return;
    			
    			for(int i=0;i<len[b[now]];i++) ans[c[b[now]][i]]=-ans[c[b[now]][i]];
    			dfs(now+1,sum+ans[now]);
    			if(flag) return;
    			
    			for(int i=0;i<len[b[now]];++i) ans[c[b[now]][i]]=0;
    		}
    		else dfs(now+1,sum+ans[now]);
    	}
    	inline void main()
    	{
    		n=read();
    		for(int i=1;i<=n;++i) link(read(),i);
    		for(int i=1;i<=n;++i)
    			if(!vis[i]) search(i);
    		dfs(1,0);
    	}
    }
    signed main()
    {
    	red::main();
    	return 0;
    }
    
  • 相关阅读:
    小tips: HTTP 请求过程示例图及名称解释
    小tips:使用vuecli2脚手架配置vant自定义主题
    axios使用备忘录
    知乎问题:为什么很多web项目还是使用 px,而不是 rem?
    小tips:HTML5的ruby标签实现给汉字加拼音、details标签实现折叠面板、原生进度条progress和度量meter
    ES6之常用开发知识点:入门(一)
    GitBook相关使用以及配置笔记
    小tips:使用vue-cli脚手架搭建项目,关于eslint语法检测配置
    小tips:JS/CSS实现字符串单词首字母大写
    vue动态子组件的实现方式
  • 原文地址:https://www.cnblogs.com/knife-rose/p/12771244.html
Copyright © 2020-2023  润新知