zoukankan      html  css  js  c++  java
  • test20190305

    • 上午考试,是 (SCOI 2016 Day 1) 的题目.

    背单词

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		fh=-1,jp=getchar();
    	while (jp>='0'&&jp<='9')
    		out=out*10+jp-'0',jp=getchar();
    	return out*fh;
    }
    const int MAXN=1e5+10,MAXL=510010,Siz=26;
    int N;
    int idx,dfn,tot;
    ll ans;
    int ch[MAXL][Siz];
    int val[MAXL];
    void ins(char *s,int n,int v)
    {
    	int u=0;
    	for(int i=n-1; i>=0; --i)
    		{
    			int k=s[i]-'a';
    			if(!ch[u][k])
    				ch[u][k]=++idx;
    			u=ch[u][k];
    		}
    	val[u]=v;
    }
    int cnt=0,head[MAXN],to[MAXN<<1],nx[MAXN<<1];
    int siz[MAXN];
    inline void addedge(int u,int v)
    {
    	++cnt;
    	to[cnt]=v;
    	nx[cnt]=head[u];
    	head[u]=cnt;
    }
    void bg(int u,int lst)
    {
    	if(val[u])
    		{
    			addedge(lst,val[u]);
    			lst=val[u];
    		}
    	for(int k=0; k<Siz; ++k)
    		{
    			if(!ch[u][k])
    				continue;
    			bg(ch[u][k],lst);
    		}
    }
    void getsiz(int u)
    {
    	siz[u]=1;
    	for(int i=head[u];i;i=nx[i])
    		{
    			int v=to[i];
    			getsiz(v);
    			siz[u]+=siz[v];
    		}
    }
    typedef pair<int,int> pii;
    int vis[MAXN];
    pii tmp[MAXN];
    stack<int> stk;
    void dfs(int u,int fa)
    {
    	int pos=0;
    	vis[u]=++tot;
    	ans+=vis[u]-vis[fa];
    	for(int i=head[u];i;i=nx[i])
    		{
    			int v=to[i];
    			tmp[++pos]=make_pair(-siz[v],v);
    		}
    	sort(tmp+1,tmp+1+pos);
    	for(int i=1;i<=pos;++i)
    		stk.push(tmp[i].second);
    	while(pos--)
    		{
    			int v=stk.top();
    			stk.pop();
    			dfs(v,u);
    		}
    }
    void solve()
    {
    	bg(0,0);
    	getsiz(0);
    	dfn=0;
    	dfs(0,0);
    	cout<<ans<<endl;
    }
    char buf[MAXL];
    int main()
    {
    	freopen("word.in","r",stdin);
    	freopen("word.out","w",stdout);
    	int N=read();
    	for(int i=1; i<=N; ++i)
    		{
    			scanf("%s",buf);
    			int n=strlen(buf);
    			ins(buf,n,i);
    		}
    	solve();
    	return 0;
    }
    

    幸运数字

    • 标算应该是 (O(nlogn*60+Q*60^2)) 的点分治...难得写离线挂询问,就写了 (O(Qlogn*logn*60^2)) 的树剖暴力搞...(其实跑不满)没开 (O2) ,被卡了一个点. (ljq) 同样的做法却 (A) 了,只跑了我的一半时间...
    • 树剖的做法比较显然,直接用线段树维护区间内所有数字的线性基,合并时暴力合并,因为数字不会占满 (60) 位,合并时就跑不满 (60*60) ,优化一下常数是能过的.
    • 点分治的做法比较类似,求出重心到各个点路径上数字的线性基后,也是暴力合并线性基,但只在询问时合并.
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		fh=-1,jp=getchar();
    	while (jp>='0'&&jp<='9')
    		out=out*10+jp-'0',jp=getchar();
    	return out*fh;
    }
    const int MAXN=2e4+10;
    int n;
    int cnt=0,head[MAXN],to[MAXN<<1],nx[MAXN<<1];
    void addedge(int u,int v)
    {
    	++cnt;
    	to[cnt]=v;
    	nx[cnt]=head[u];
    	head[u]=cnt;
    	swap(u,v);
    	++cnt;
    	to[cnt]=v;
    	nx[cnt]=head[u];
    	head[u]=cnt;
    }
    ll w[MAXN];
    int idx=0,fa[MAXN],dfn[MAXN],rnk[MAXN],siz[MAXN],mxson[MAXN],top[MAXN],dep[MAXN];
    void dfs1(int u,int Fa)
    {
    	siz[u]=1;
    	fa[u]=Fa;
    	dep[u]=dep[Fa]+1;
    	for(int i=head[u];i;i=nx[i])
    		{
    			int v=to[i];
    			if(v==Fa)
    				continue;
    			dfs1(v,u);
    			siz[u]+=siz[v];
    			if(siz[v]>siz[mxson[u]])
    				mxson[u]=v;
    		}
    }
    void dfs2(int u,int tp)
    {
    	++idx;
    	dfn[u]=idx;
    	rnk[idx]=u;
    	top[u]=tp;
    	if(mxson[u])
    		dfs2(mxson[u],tp);
    	for(int i=head[u];i;i=nx[i])
    		{
    			int v=to[i];
    			if(v==fa[u] || v==mxson[u])
    				continue;
    			dfs2(v,v);
    		}
    }
    namespace SEG{
    	struct node{
    	int l,r;
    	ll v[62];
    	void init(){memset(v,0,sizeof v);}
    	node(){init();}
    	void ins(ll x)
    		{
    			for(int i=61;i>=0;--i)
    				{
    					if((x>>i) & 1)
    						{
    							if(!v[i])
    								{
    									v[i]=x;
    									break;
    								}
    							x^=v[i];
    						}
    				}
    		}
    	ll mxv()
    		{
    			ll ans=0;
    			for(int i=61;i>=0;--i)
    				if((ans^v[i])>ans)
    					ans^=v[i];
    			return ans;
    		}
    	friend node operator + (const node &a,const node &b)
    		{
    			node res=a;
    			for(int i=0;i<=61;++i)
    				if(b.v[i])
    					res.ins(b.v[i]);
    			return res;
    		}
    	}Tree[MAXN<<2];
    	node res;
    #define root Tree[o]
    #define lson Tree[o<<1]
    #define rson Tree[o<<1|1]
    	inline void pushup(int o)
    	{
    		int l=root.l,r=root.r;
    		root=lson+rson;
    		root.l=l,root.r=r;
    	}
    	void BuildTree(int o,int l,int r)
    	{
    		root.l=l,root.r=r;
    		if(l==r)
    			{
    				root.ins(w[rnk[l]]);
    				return;
    			}
    		int mid=(l+r)>>1;
    		BuildTree(o<<1,l,mid);
    		BuildTree(o<<1|1,mid+1,r);
    		pushup(o);
    	}
    	void query(int o,int L,int R)
    		{
    			int l=root.l,r=root.r;
    			if(l>R || L>r)
    				return;
    			if(L<=l && r<=R)
    				{
    					res=res+root;
    					return;
    				}
    			int mid=(l+r)>>1;
    			if(L<=mid)
    				query(o<<1,L,R);
    			if(R>mid)
    				query(o<<1|1,L,R);
    		}
    }
    using namespace SEG;
    void solve(int x,int y)
    {
    	res.init();
    	while(top[x]!=top[y])
    		{
    			if(dep[top[x]]<dep[top[y]])
    				swap(x,y);
    			query(1,dfn[top[x]],dfn[x]);
    			x=fa[top[x]];
    		}
    	if(dep[x]<dep[y])
    		swap(x,y);
    	query(1,dfn[y],dfn[x]);
    	printf("%lld
    ",res.mxv());
    }
    int main()
    {
    	freopen("lucky.in","r",stdin);
    	freopen("lucky.out","w",stdout);
    	n=read();
    	int Q=read();
    	for(int i=1;i<=n;++i)
    		scanf("%lld",&w[i]);
    	for(int i=1;i<n;++i)
    		{
    			int u=read(),v=read();
    			addedge(u,v);
    		}
    	dfs1(1,0);
    	dfs2(1,1);
    	BuildTree(1,1,n);
    	while(Q--)
    		{
    			int x=read(),y=read();
    			solve(x,y);
    		}
    	return 0;
    }
    

    萌萌哒

    • 用并查集维护,钦定了相同的位置被归在一个联通块中,若共有 (b) 个联通块,最后答案显然为 (9*10^{b-1}).
    • 场上做法:对每个限制条件暴力合并,时间复杂度为 (O(n^2)) .获得 (30) 分好成绩.
    • 要注意到限制条件都是限制一段连续区间,而不是离散的 (n^2) 个限制.可以在并查集上用上 (ST) 表的思想.
    • (fa[k][i]) 表示从位置 (i) 开始的 (2^k) 个元素的并查集代表元素.也就是说,若 (fa[k][i]=fa[k][j]) ,则 ([i,i+2^k-1])([j,j+2^k-1]) 这两段区间元素是相等的.
    • 这个合并是可以重叠的,合并区间时合并前半段和后半段即可.
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		fh=-1,jp=getchar();
    	while (jp>='0'&&jp<='9')
    		out=out*10+jp-'0',jp=getchar();
    	return out*fh;
    }
    const int P=1e9+7;
    inline int mul(int a,int b)
    {
    	return 1LL * a * b % P;
    }
    int fpow(int a,int b)
    {
    	int res=1;
    	while(b)
    		{
    			if(b&1)
    				res=mul(res,a);
    			a=mul(a,a);
    			b>>=1;
    		}
    	return res;
    }
    const int MAXK=20,MAXN=1e5+10;
    int fa[MAXK][MAXN];
    int Find(int k,int x)
    {
    	if(x==fa[k][x])
    		return x;
    	return fa[k][x]=Find(k,fa[k][x]);
    }
    void Merge(int k,int x,int y)//合并[x,x+2^k-1],[y,y+2^k-1]
    {
    	int u=Find(k,x),v=Find(k,y);
    	if(u!=v)
    		{
    			fa[k][u]=v;
    			if(!k)
    				return;
    			Merge(k-1,x,y);
    			Merge(k-1,x+(1<<(k-1)),y+(1<<(k-1)));
    		}
    }
    int n,m;
    int main()
    {
    	n=read(),m=read();
    	for(int k=0;k<MAXK;++k)
    		for(int i=1;i<=n;++i)
    			fa[k][i]=i;
    	for(int i=1;i<=m;++i)
    		{
    			int L1=read(),R1=read(),L2=read(),R2=read();
    			int k=floor(log2(R1-L1+1));
    			Merge(k,L1,L2);
    			Merge(k,R1-(1<<k)+1,R2-(1<<k)+1);
    		}
    	int blocks=0;
    	for(int i=1;i<=n;++i)
    		if(fa[0][i]==i)
    			++blocks;
    	int ans=mul(9,fpow(10,blocks-1));
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    NPOIHelper.cs (NPOI 2.1.1)
    使用哈希加盐法来为密码加密【转】
    让普通控件拥有左键移动窗体的功能
    Reflector反编译.NET文件后修复【转】
    SD卡中FAT32文件格式快速入门(图文详细介绍)【转】
    项目管理知识体系指南(PMBOOK指南)(第5版) 阅读摘要
    数学
    位运算小结
    字符串(1)——Detect Capital
    数组和矩阵(3)——Next Greater Element I
  • 原文地址:https://www.cnblogs.com/jklover/p/10476102.html
Copyright © 2011-2022 走看看