test20190305
- 上午考试,是 \(SCOI\ 2016\ Day\ 1\) 的题目.
背单词
- 这题我以前是做过的.Trie树总结.
#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\n",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;
}
test20190305的更多相关文章
随机推荐
- python 使用set对list去重,并保持list原来顺序
list_one=re.findall(r"^\s{0}[A-Za-z]*\b", txt,re.M) #匹配一级目录 addr_to = list(set(list_one))a ...
- JAXB和XStream比较
转自:https://www.cnblogs.com/tang9139/p/4825610.html http://www.cnblogs.com/wlsblog/p/7452882.html 这两东 ...
- xshell5使用ssh连接阿里云服务器
这里有两种方式,一种是在阿里云的控制台里面进行,另一种是在Xshell里面生成密钥. 阿里云控制台密钥对 点击右上方的创建密钥对 在阿里云里面生成较为简单,点击该页面右上方的“创建密钥对”,在另一个页 ...
- [spring]<context:property-placeholder/>
问题: 有些参数在某些阶段中是常量,这些参数在不同阶段之间又往往需要改变,如: 在开发阶段我们连接数据库时的url,username,password等信息 分布式应用中client端的server地 ...
- tags
运行tags在你的.vimrc 中加一个路径,set tags=/home/lh/1407k/arm/tags 注意此文件下的东西要注销必须用“执行一个ctags -R *;ctrl + ]过去,ct ...
- PHP stream相关协议及上下文选项和参数归纳
支持的协议和封装协议 PHP 带有很多内置 URL 风格的封装协议,可用于类似 fopen(). copy(). file_exists() 和 filesize() 的文件系统函数. 除了这些封装协 ...
- JSP 国际化
在开始前,需要解释几个重要的概念: 国际化(i18n):表明一个页面根据访问者的语言或国家来呈现不同的翻译版本. 本地化(l10n):向网站添加资源,以使它适应不同的地区和文化.比如网站的印度语版本. ...
- @DataProvider的应用
代码中经常有一些数据需要维护,但是每次都写在一个class或者methods中,维护起来是个麻烦事: 这里引入@DataProvider的思想,建一个DataProvider的方法,让我们需要维护的数 ...
- Linux命令详解-date
在linux环境中,不管是编程还是其他维护,时间是必不可少的,也经常会用到时间的运算,熟练运用date命令来表示自己想要表示的时间,肯定可以给自己的工作带来诸多方便. 1.命令格式: date [ ...
- 002——vue小结
1.new 一个vue对象的时候你可以设置他的属性,其中最重要的包括三个,分别是:data,methods,watch. 2.其中data代表vue对象的数据,methods代表vue对象的方法,wa ...