bzoj

BZOJ 2733: [HNOI2012]永无乡

爷,独闯天下 提交于 2020-01-22 22:16:53
初始给定一个n个点m条边的无向图,q次操作,每次要么新增一条边,要么查询与某个点相连的所有点里点权第K小的点的编号。 查询联通分量容易想到并查集,查询第K大需要用平衡树,容易想到每个联通分量维护一棵平衡树, 每次新增加一条边对联通分量的影响就是合并两颗平衡树,为了保障复杂度正确,我们采用启发式合并,每次把小的联通分量的每个值暴力插到大的联通分量中, 简单来看,启发式合并一次,容量至少对小的联通分量来说是翻倍,再加上插入平衡树的均摊复杂度是O(logn)的,乍一看复杂度是O(nlog^2n)的 (不过camp讲课的时候说,把小的Splay的每个数值从小到大插入到大的Splay中,时间复杂度是O(nlogn)的,证明需要用到Dynamic Finger Theorem) 然后,貌似就做完了 #include<bits/stdc++.h> using namespace std; const int maxn=5e5; const int INF=0x3f3f3f3f; typedef long long ll; struct Splay { int ch[2]; int fa; int cnt,val,sz; }b[maxn+5]; int father[maxn+5]; int tot=0,root[maxn+5]; inline int newNode(int fa,int val

BZOJ 5544: [PA2019]A + B

巧了我就是萌 提交于 2020-01-22 21:23:54
5544: [PA2019]A + B Time Limit: 1 Sec Memory Limit: 256 MB Submit: 16 Solved: 13 [ Submit ][ Status ][ Discuss ] Description 在列竖式计算两个十进制数的和的时候,人们可能会错算成这样: 在图里的左边,248+208被错算成了4416。 给定正整数n,问有多少对非负整数a,b满足a+b会被错算成n。请注意a可以等于b,且a=1,b=2和a=2,b=1是两种不同的方案。 Input 第一行包含一个正整数n(1<=n<10^18)。 Output 输出一个整数,即满足条件的a,b的数量。 Sample Input 112 Sample Output 50 HINT Source 鸣谢Claris上传 [ Submit ][ Status ][ Discuss ] 老年人好久没来BZOJ做题了…… 数位DP,F[i]表示前i位方案数,转移有两种—— 1. 第i位由一对数字加出 2. 第i位和第i-1位一起由一对数字加出 1 #include <iostream> 2 #include <algorithm> 3 4 using namespace std; 5 6 typedef long long Int; 7 8 int main() { 9 Int n; 10

BZOJ 3837 [Pa2013]Filary

久未见 提交于 2020-01-22 18:19:30
Link 如果我们现在钦定了某一个数强制选,那么我们就是要选择最多的数使得它们的 \(\gcd\ne1\) 。这个可以在预处理完每个数的最小质因子之后检查每个质因子有多少个倍数即可。 可以发现 \(k\ge\lceil\frac n2\rceil\) ,当 \(m=2\) 时可以直接取到。 因此我们钦定某个数,它出现在最优答案中的概率至少是 \(\frac12\) ,随机 \(t\) 次之后正确率可以达到 \(1-\frac1{2^t}\) 。 #include<cstdio> #include<cctype> #include<cstdlib> int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;} int abs(int x){return x<0? -x:x;} int gcd(int n,int m){return !n||!m? n+m:gcd(m,n%m);} const int N=100007,M=10000007; int pr[M>>3],f[M],a[N],t1[M],t2[M]; int main() { int tot=0,n=read(),a1=0,a2=0; for(int i=1;i

[bzoj十连测]Problem

廉价感情. 提交于 2020-01-21 04:03:52
找不到题,没有代码 q w q qwq q w q 一、题目 题目描述 有一颗字典树 t i r e tire t i r e ,现在每次加入一个叶子,你需要回答这个点到根路径代表的字符串的最长公共前缀后缀是多少,强制在线。 数据范围 节点数,操作数,字符集大小均为 100000 100000 1 0 0 0 0 0 以内。 二、解法 最长公共前缀后缀显然是 k m p kmp k m p ,但是 k m p kmp k m p 的均摊复杂度分析在树上就失效了,我们要用其他方法。 0x01 trans的优化 考虑数组 t r a n s [ x ] [ c ] trans[x][c] t r a n s [ x ] [ c ] 表示在 x x x 后面安放 c c c 最后会跳到的地方(用来最长公共前缀递推),有下列柿子: f a i l [ x ] = t r a n s [ f a i l [ f a x ] ] [ s x ] fail[x]=trans[fail[fa_x]][s_x] f a i l [ x ] = t r a n s [ f a i l [ f a x ​ ] ] [ s x ​ ] 所以我们只需要维护出 t r a n s trans t r a n s 即可,可以用可持久化线段树,我们的 t r a n s trans t r a n s 直接拷贝

@bzoj - 4259@ 残缺的字符串

浪尽此生 提交于 2020-01-20 20:23:21
目录 @description@ @solution@ @accepted code@ @details@ @description@ 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n。可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同程度的残缺。 你想对这两个串重新进行匹配,其中A为模板串,那么现在问题来了,请回答,对于B的每一个位置i,从这个位置开始连续m个字符形成的子串是否可能与A串完全匹配? 原题链接。 @solution@ 据说已经成了套路题。 以下内容中假定以 0 为字符串下标起点。 考虑没有通配符的情况,B 中第 j 个位置开头的串能否与 A 匹配。实际上是计算式子 \(\sum_{i=0}^{m-1}[A_i\not = B_{i+j}]\) 是否为 0。 注意到这个注意匹配的形式很像卷积。不过别急,我们先把其拆成数值计算的形式:上式为 0 等价于 \(\sum_{i=0}^{m-1}(A_i - B_{i+j})^2\) 。 由完全平方的非负性可以得到等价性。 有通配符怎么办?A, B 其中一个为通配符,构造出来的式子就应该等于 0。 不妨令通配符等于 0,则计算 \(\sum_{i=0}^{m-1}(A_i - B_{i+j})^2\times A_i \times B_{i+j}\)

BZOJ 2648 世界树

ⅰ亾dé卋堺 提交于 2020-01-17 17:54:29
题目 传送门 分析: 喜 闻 乐 见 的虚树 但是建好虚树后的DP也非常的恶心 我们先考虑每个关键点的归哪个点管 先DFS一次计算儿子节点归属父亲 再DFS一次计算父亲节点归属儿子 然后然后我们对于虚树上的每条边计算一下 首先先找到分割点mid 那么向上归属的是红色部分 向下的是绿色部分 对于每条边都算一下就好了 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #define maxn 600005 #define INF 1ll<<50 using namespace std; inline int getint() { int num=0,flag=1;char c; while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1; while(c>='0'&&c<='9')num=num*10+c-48,c=getchar(); return num*flag; } int n; int fir[maxn],nxt[maxn],to[maxn],cnt; int f[maxn][21],dpt[maxn],sz[maxn]; int h[maxn],a[maxn]; int bl[maxn],F[maxn],ans

BZOJ 2132 圈地计划 最小割

六眼飞鱼酱① 提交于 2020-01-16 18:50:54
首先黑白染色 因为相邻的节点颜色必不同 相同颜色的节点之间没有关系(没有边) 然后Add(S,黑色点,A[i][j]) (黑色点,T,B[i][j])(S,白色点,B[i][j])(白色点,T,A[i][j])因为黑色点和白色点同属一个S/T才有额外贡献 所以这里A[i][j],B[i][j]要交换连 sum初始为矩阵里每个点的A,B之和 对于每个点 向它四周相邻的点连(u,v,C[i][j]+C[i'][j']) 注意这里黑色到白色 白色到黑色都要连 因为有属于S/T两种情况 然后一个点有X个相邻点则sum+=X*C[i][j] 因为上面连的C[i][j]+C[i'][j']容量的边其实有两条但是却不存在同时切两条的情况 最多只会切一条 #include<bits/stdc++.h> using namespace std; typedef long long ll; typedef int JQK; int n, m;int dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}}; int bl[105][105]; int sum = 0; int A[105][105], B[105][105], C[105][105]; int main() { int n, m; scanf("%d %d", &n, &m); dinic:

【bzoj 2132】圈地计划(最小割)

廉价感情. 提交于 2020-01-16 03:09:50
Time Limit: 2 Sec Memory Limit: 256 MB Submit: 923 Solved: 418 [Submit][Status][Discuss] Description 最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地。据了解,这块土地是一块矩形的区域,可以纵横划分为N×M块小区域。GDOI要求将这些区域分为商业区和工业区来开发。根据不同的地形环境,每块小区域建造商业区和工业区能取得不同的经济价值。更具体点,对于第i行第j列的区域,建造商业区将得到Aij收益,建造工业区将得到Bij收益。另外不同的区域连在一起可以得到额外的收益,即如果区域(I,j)相邻(相邻是指两个格子有公共边)有K块(显然K不超过4)类型不同于(I,j)的区域,则这块区域能增加k×Cij收益。经过Tiger.S教授的勘察,收益矩阵A,B,C都已经知道了。你能帮GDOI求出一个收益最大的方案么? Input 输入第一行为两个整数,分别为正整数N和M,分别表示区域的行数和列数;第2到N+1列,每行M个整数,表示商业区收益矩阵A;第N+2到2N+1列,每行M个整数,表示工业区收益矩阵B;第2N+2到3N+1行,每行M个整数,表示相邻额外收益矩阵C。第一行,两个整数,分别是n和m(1≤n,m

BZOJ 1015 [星球大战 starwar]

江枫思渺然 提交于 2020-01-14 07:48:59
题面 题意   给定无向图,每次删去一个点并求连通分量个数。 题解   很难在删除点的同时维护联通分量个数,但是如果把操作倒序,问题就变成了每次往无向图里添加一个点并求连通分量个数。可以用并查集维护。 代码 #include<iostream> #include<cstdio> #include<vector> using namespace std; const int maxn=4e5+5; vector<int> e[maxn]; int fa[maxn]; bool vis[maxn]; int arr[maxn],ans[maxn]; int ff(int u){ return fa[u]==u?u:fa[u]=ff(fa[u]); } int main(){ int i,j,n,m; int u,v; int cnt; scanf("%d%d",&n,&m); while (m--){ scanf("%d%d",&u,&v); e[u].push_back(v); e[v].push_back(u); } scanf("%d",&m); for (i=0;i<n;i++){ fa[i]=i; vis[i]=true; } for (i=0;i<m;i++){ scanf("%d",&arr[i]); vis[arr[i]]=false; } cnt=n-m; for

BZOJ 2115: [Wc2011] Xor 线性基

依然范特西╮ 提交于 2020-01-10 14:41:19
这个题的思路非常神啊,感觉不太好理解... code: #include <cstdio> #include <algorithm> #include <cstring> #include <string> #define N 100006 #define ll long long using namespace std; namespace IO { void setIO(string s) { string in=s+".in"; string out=s+".out"; freopen(in.c_str(),"r",stdin); // freopen(out.c_str(),"w",stdout); } }; int n,m,edges; int hd[N],to[N<<1],nex[N<<1],vis[N]; ll bin[65],p[65],val[N<<1],sum[N]; void add(int u,int v,ll c) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c; } struct Base { ll p[65]; void insert(ll x) { for(int i=61;i>=0;--i) { if(x&bin[i]) { if(p[i]) x^=p[i]; else { p[i