摘要:大原来做的一道题,偷懒直接粘的原来的程序 http://www.cnblogs.com/BLADEVIL/p/3433520.html/**************************************************************Problem: 3035User: BLADEVILLanguage: PascalResult: AcceptedTime:240 msMemory:4216 kb****************************************************************///By BLADEVILvarn,...
阅读全文
摘要:因为是数列的维护,所以我们可以考虑用splay来维护,每次在x插入的时候就在x+1前面插入就行了,然后用bst来维护两问的答案,但是应该会tle。我们来考虑这个问题的性质,首先因为这个数列没有删除操作,所以每个数插入进去之后就不会出来了,换句话说,就是假设insert(x,y)那么y这个值和前面的那个数可以更新相邻差值的答案,且这个不会因为其他的插入操作而使得这个差值消失(消失值类似(x,y)插入,那么之前在x处插入的点与x+1的差值会消失),所以我们只需要存储每个位置最后插入的数,那么对于一个插入(x,y)我们只需要判断x位置是否插入过值然后讨论就行了。那么对于另一个全局差值的更新我们只..
阅读全文
摘要:首先比较明显的是如果存在一个半连通子图,我们将其中的环缩成点,那么该图仍为半连通子图,这样我们就可以先将整张图缩点,重新构图,新图为拓扑图,记录每个新的点表示的强连通分量中点的个数num[i],那么我们就可以DP了,新图中的每一条链都为原图的半连通子图,这样我们找到新图中的最长链就行了,找入度为0的点dfs做树上DP,这样我们可以知道每个点的len[i]代表从这个点开始的最长链的长度,len[i]=max(len[son of i])+num[i],然后我们求出来了第一问,对于第二问,我们需要找len[i]=ans1的点做dfs,然后设ans[i]为以i为根的子树的方案数,那么ans[i]..
阅读全文
摘要:每一种颜色存一颗二维树状数组,然后直接做就行了。/**************************************************************Problem: 1452User: BLADEVILLanguage: C++Result: AcceptedTime:4844 msMemory:36904 kb****************************************************************///By BLADEVIL#include #include #define maxn 301#define maxc 101..
阅读全文
摘要:在1-n所有数中,i一共可以成为n/i个数的约数,也即所有的约数中有n/i个i,所以扫一遍累加答案就好了。/**************************************************************Problem: 1968User: BLADEVILLanguage: C++Result: AcceptedTime:32 msMemory:804 kb****************************************************************///By BLADEVIL#include int n,ans;int ma..
阅读全文
摘要:首先如果我们想取得分最高的话,肯定尽量赢,实在赢不了的话就耗掉对方最高的,那么就有了贪心策略,先排序,我方最弱的马和敌方最弱的相比,高的话赢掉,否则耗掉敌方最高的马。 对于一场比赛,总分是一定的,所以两问实际上是等效的。/************************************************************** Problem: 1034 User: BLADEVIL Language: C++ Result: Accepted Time:264 ms Memory:1588 kb*******************...
阅读全文
摘要:比较容易看出来是DP,但是如果我们记录每一种颜色还剩多少种的话,消耗的转移的时间复杂度5^15,但是我们考虑到每一种颜色,如果数量相同的话,其实是等效的,所以我们用w[a][b][c][d][e][last]记录还剩下1,2,3,4,5次使用次数的颜色的数量为a,b,c,d,e,上一次我们那的是使用次数剩余为last的颜色,那么这次在剩余last-1次的颜色中,我们只能少拿一次,因为不能拿相同的,这样转移就很容易的表示出来了。 我把存状态的数组都开到20就在0mstle了,改到16就好了,求指导。。。/*******************************************...
阅读全文
摘要:首先我们知道若干区间和信息,判断给出信息是否合法,可以用并查集维护,我们用dis[x]表示x到father[x]的距离为多少,即区间father[x]到x的长度,这样我们可以在路径压缩的时候维护dis,对于加进来的x,y区间,如果两点祖先不相同,那么合并,相同的话判断是否和已知的信息相符,这样就可以了。 需要注意的是为了防止x==y的情况发生,对于区间1,2和3,3,本来是连通的区间,但是因为读入为闭区间,所以需要将y++来使得区间向连通。/************************************************************** Problem:...
阅读全文
摘要:因为询问比较少,所以我们可以将n个数分成sqrt(n)个块,每个块用一颗bst存一下,然后对于修改l,r,我们将l,r区间中整块的直接在bst上打一个标签,对于不是整块的我们直接暴力修改,对于询问l,r,仍然是整块的直接在bst中求大于c的个数(考虑标签),然后不是整块的部分暴力扫一遍更新答案。 我写的sbt,可能是sbt常数比较大什么的,tle了,其实对于每一个块我们可以快排保存,然后询问的时候二分就好了。然后对于不是整块的修改和询问可以直接改完之后再快排,这样常数小了很多。 懒得改了,贴sbt的吧。/*****************************************...
阅读全文
摘要:我们可以用一颗平衡树维护每个人的工资,因为工资的变化会影响到后面所有的人,所以我们打一个标签,向平衡树里插入的时候减去这个标签的值,这样代表改变了之后的零点,,这样维护这个标签就好了,输出的时候要加上这个标签。 反思:]后面打了个|,查了半天。。/************************************************************** Problem: 1503 User: BLADEVIL Language: C++ Result: Accepted Time:676 ms Memory:3932 kb******...
阅读全文
摘要:根据陈丹琪的论文弦图与区间图,求出弦图的完美消除序列之后,反向给每个点染可以染的最小的颜色,这样可以使用最少的颜色染色,染色的方案即为队伍数。 那么我们需要求该图的完美消除序列,使用MCS算法,从后向前求完美消除序列,我们设size[i]为i这个点的标号,表示该点与多少个以标记的点相连,选取标号最大且i最大的点(即n)为序列的第n个,然后更新与i相连的点的标号,重复n次,即可得到弦图的完美消除序列,使用动态链表维护可以使时间复杂度达到O(m+n),暴力循环也有n^2,这道题暴力即可过。/***************************************************...
阅读全文
摘要:AC自动机是处理多模式串匹配等一系列问题的工具,可以将它当做一种数据结构。 首先我们考虑一个非常简单的问题,给定两个字符串,询问其中一个字符串在另一字符串中出现的次数,这个问题我们用KMP就可以非常容易的解决了,但是如果给定若干模式串,询问这组串在这个长串中的各个出现次数,这时KMP的时间复杂度就显然比较暴力了,对于这类的问题,我们可以考虑用AC自动机来解决(假设字符串中字符为大写字母)。 定义指针。struct node{ int cnt; node *fail,*child[30]; node(){ cnt=0; fail=NULL; ...
阅读全文
摘要:首先对于双关键字的LIS有一个比较暴力的方法,就是线段树套平衡树,我们把双关键字的LIS抽象成二维坐标系中的点,这样我们对于当前转移的点i(x,y),需要找的就是在(xx,yy)xx<x,yy<y中的决策点的最大值是多少,这样我们用线段树维护第一维坐标,用sbt或者是线段树维护第二维坐标,这样就可以了。 但是树套树的常数非常大,将线段树改为BIT之后虽然对常数有一些优化,但还是较大,所以我们需要考虑另一种方法。 在求单关键字的LIS的时候,有一种nlogn的二分做法,大概意思是维护一个b[i]数组,对于第i位b[i]代表长度为i的上升子序列的最后一位最小的值,那么在二维的情况下,我
阅读全文
摘要:我们用w[i]表示到第i个地鼠出现的时候,我们选了第i个地鼠,能得到的最大的价值,那么显然有转移w[i]=w[j]+1(time[i]-time[j]>=abs(x[i]-x[j])+abs(y[i]-y[j]))。每次转移为O(1)的,一共转移了Σi(i#include #define maxm 10010using namespace std;int n,m,ans;int time[maxm],x[maxm],y[maxm],w[maxm];int main(){scanf("%d%d",&n,&m);for (int i=1;i=abs(x[i
阅读全文
摘要:首先我们二分一个答案mid,在判定是否能举办mid次,那么对于每个次我们可以用最大流根据是否满流(流量为n*mid)来判定,对于每个点我们拆成两个点,分别表示这个人要和他喜欢和不喜欢的人一起跳舞,那么添加源点source,汇点sink,设i为男生,j为女生,那么连接表示这个人要跳mid次,同理连接,这样我们保证了每个人都是跳了mid次舞,那么对于每一对儿喜欢关系i,j,连接,对于不喜欢的i,j连接,那么我们保证了每个人都可以和所有人跳舞,对于i中的每个点连接代表这个人最多和k个不喜欢的人跳舞,同理对于j中的每个人连接,因为每次和不喜欢的人跳舞,一定会经过这条边,所以保证了最多不会和超过k的..
阅读全文
摘要:首先对于m==1的情况非常容易处理(其实这儿因为边界我错了好久。。。),直接DP就好了,设f[i][k]为这个矩阵前i个选k个矩阵的最大和,那么f[i][k]=max(f[j][k-1]+sum[j+1][i]),那么对于m==2的时候类似与m=1的时候,设w[i][j][k]为左面的一行前i个中,右面的一行前j个中,一共选k个矩阵能选取得最大矩阵。 那么转移也比较明显,有一下几种转移 w[i][j][k]=max(w[i-1][j][k],w[i][j-1][k])这种情况代表什么都不选。 w[i][j][k]=max(w[ii][j][k-1]+sum[ii+1][i][0])这...
阅读全文
摘要:就是bfs,对于每个状态存一个hash为当前状态矩阵的二进制表示,然后搜就行了,写成双向bfs会快很多。 反思:对于C++的数组从0开始还不是特别习惯,经常犯错,对于C++的结构体不熟。/************************************************************** Problem: 1054 User: BLADEVIL Language: C++ Result: Accepted Time:112 ms Memory:1940 kb************************************...
阅读全文
摘要:首先我们可以枚举每个一点,然后向下一直拓展到不能拓展为止,然后向下拓展的同时我们可以算出来向左最多拓展的个数,用单调栈来维护一个上升的序列,这样就类似与悬线法找最大01子矩阵了,但是对于这题01交替来说,好多细节比较麻烦,所以我们可以采用另一种转换方法,对于一个01矩阵来说,一定满足一下两个条件中的一个: 1:矩阵中所有0的点(i,j),i与j的奇偶相同,且对于所有1点(i,j),i与j的奇偶不同。 2:矩阵中所有0的点(i,j),i与j的奇偶不同,且对于所有1点(i,j),i与j的奇偶相同。 那么我们把所有满足1条件的点标号为1,满足2条件的点标号为0,这样,我们就求出标号矩阵的01子...
阅读全文
摘要:首先我们知道ans=Σ(h[i]*f[i])=Σ(h[i]*d[i])/s=Σ(k(r[i]+1)+c)*d[i]/s=Σ(k*r[i]+(k+c))*d[i]/s 我们可以发现,除了k*r[i]之外,剩下的都是常数,那么我们这道题就转化成了求k*r[i]的最小值,那么区间dp就可以了,对于区间i,j,每次选取一个k为根,由左右两个区间转移过来,相当于将左右子树所有的深度+1,那么增加的代价就为两区间和,这样转移就可以了。 对于第二问我们可以在转移的时候记录每个区间的最优决策点,也即选取的根,那么最后递归生成遍历就行了,但是bz上没有第二问,不用输出。 反思:带错数据,将自己造的一组...
阅读全文
摘要:假设我们知道以每个点开始到最后的最长上升序列,设为w[i],这样首先我们在w值中取max,如果询问的值比max大,这样显然就是无解,如果小的话,我们需要求出来字典序最小的方案。 那么对于所有i,我们肯定以w[i]大于询问的值中的最小的i开始,那么假设上升序列中第一个值为i,第二个值为j,那么w[j]满足大于询问的值-1,且初始序列a中,a[j]的值要大于a[i],且为最小的j,对于最小的我们只需要通过循环正常的枚举就行了。 那么我们现在剩下的问题就是w[i]值如何求,如果n小一些的话我们就可以n^2正常的做了,但是n为10^4,这样我们就需要维护单调队列que[i],表示长度为i的最长...
阅读全文
摘要:首先根据样例或者自己打表大概可以知道,对于询问k,答案不会超过k#include #include #define maxn 50010 using namespace std; long long mindiv[maxn],prim[maxn],miu[maxn]; void prepare(){ miu[1]=1; for (long long i=2;i>1; //printf("%d %d %d\n",l,r,mid); if (calc(mid)>=n) { ans=mid...
阅读全文
摘要:首先我们可以做一遍dfs,用一个队列记录每个点进出的顺序,当每个点访问的时候que[tot++]=x,记为in[x],当结束dfs的时候que[tot++]=x,记为out[x],这样处理出来的队列,如果我们将一个数的进队赋值为1,出队赋值为-1,那么假设我们需要询问1-x的链中共有多少个点,答案就是这个队列前int[x]项,所以我们开始dfs1处理出来in,out数组,然后用树状数组维护这个队列,就行了。 /************************************************************** Problem: 1103 User: B...
阅读全文
摘要:用set存下就好了。/************************************************************** Problem: 1588 User: BLADEVIL Language: C++ Result: Accepted Time:180 ms Memory:1468 kb****************************************************************/ //By BLADEVIL#include #include #define inf 1bt; bt....
阅读全文
摘要:先按边长排序,假设s与t连通,那么我们可以枚举s与t的路径中最短的一条边,通过类似与kruskal的方法找到s与t的路径在当前最小边权情况下尽量小的最大边权,用这个比值更新答案。 特别的,我们对于某一情况,如果循环完边之后s与t不连通可以跳出。在确定了最小边找完最大边的时候,不必要继续枚举最小边+1,可以从最大边开始向前加边,找到最大的边保证s,t连通,且最大边为刚才求得的,更新答案,从这个边继续枚举。这两个为优化。 反思:判断更新答案的时候手残打错,找了快一个小时才找到错。 /*****************************************************...
阅读全文
摘要:首先我们知道,对于这张图,我们可以枚举坍塌的是哪个点,对于每个坍塌的点,最多可以将图分成若干个不连通的块,这样每个块我们可能需要一个出口才能满足题目的要求,枚举每个坍塌的点显然是没有意义的,我们只需要每个图的若干个割点,这样除去割点的图有若干个块,我们可以求出只与一个割点相连的块,这些块必须要一个出口才能满足题目的要求,每个块内有块内个数种选法,然后将所有满足一个割点相连的块的点数连乘就行了。 对于每个与一个割点相连的块必须建出口可以换一种方式理解,我们将每个块看做一个点,那么算上割点之后,这张图就变成了一颗树,只有叶子节点我们需要建立出口,因为对于非叶子节点我们不论断掉哪个点我们都有另...
阅读全文
摘要:首先我们假设两个点(i,j),(i,k)向中间移动一格,且k>j+1,那么我们可以获得的价值为k-j,这样,我们定义每个点的每个星的能量为a[(i,j)]=i*i+j*j,这样这两个点开始的能量为i*i+j*j+i*i+k*k,移动之后,两个点变为(i,j+1),(i,k-1),这时的能量为i*i+(j+1)*(j+1)+i*i+(k-1),这时的能量差为2*k-2*j,为获得价值的2倍,因为对于所有的价值获得都可以采用这样的方法,所以我们可以算出开始局面的能量和,结束局面的能量和,相减>>1就是答案。 反思:显然没有发现这个优美的性质。/******************
阅读全文
摘要:我们可以用w[i][s]来表示到第i位的方案,s代表第i位和第i+1位是否有雷的二进制串,那么我们就可以根据每一位的雷的数量转移了。/************************************************************** Problem: 1088 User: BLADEVIL Language: C++ Result: Accepted Time:20 ms Memory:1588 kb****************************************************************/...
阅读全文
摘要:首先比较容易的看出来是DP,w[i]为前i个工厂的最小费用,那么w[i]=min(w[j-1]+cost(j,i))+c[i],但是这样是不work的,复杂度上明显过不去,这样我们考虑优化DP。 设A[i]=Σp[j](0k且决策j优于决策k。 那么有w[j-1]-x[i]*A[j-1]+B[j-1]#define maxn 1000010#define LL long long using namespace std; int n;LL a[maxn],c[maxn],x[maxn],que[maxn];LL A[maxn],B[maxn],w[maxn]; double k(int...
阅读全文
摘要:这个问题就是经典的生成树记数问题,题目为spoj p104 highway。 首先我们引入Matrix-Tree定理,由kirchhoff证明,定理的概述为,对于图G,我们定义若干个矩阵, D[G],Dij=(i!=j)?0:vi;这里vi为节点i的度数。 A[G],Aij=存在边(u,v),即A为图G的连通01矩阵。 定义KirchhoffMatrix C[G]=D[G]-A[G],那么C[G]的任意一个n-1阶主子式的行列式的绝对值为图G生成树个数。这样这个问题就可以比较容易的解决了,行列式的求法为将矩阵用类似于消元的方法消成上三角矩阵(其实我也是记住的代码==)。...
阅读全文
摘要:首先我们知道MST的一些性质,对于这道题来说就是,假设我们先求出一颗MST设为G,由已知边权相同的边最多会有10条,那么假设我们在这10条边中选取size条边∈G,那么我们在这边权相同的边集E中任意选取size条有意义的边,这里的有意义的边的定义为每条边都会造成新的连通性的增加,那么边集E中所有的size条有意义的边的方案我们可以通过dfs求出,然后我们将不同边权的边的方案求连乘,就是MST的方案数。 ps:我们没有必要求一遍MST,我们可以一边做kruskal,一边维护图的连通性,然后每找到一个权值不同的边集E时深搜。 反思:做dfs的时候使用并查集维护图的连通性,但是加了路径压缩,...
阅读全文
摘要:这次去WC本来就是抱着玩儿玩儿的心态去的,结果真算是玩儿了。。。 我们去的内天北京正好下雪,结果后来等我舅接我们去八十中的时候还在外面等了半个小时,其实雪天在外面挺好的,除了旁边都是一些男程序员。后来吃饭的时候还见到了我表姐们和表弟,好长时间没见也没怎么变。 后来就到了八十中,报道的时候排队就等了一个多小时,后来去了宿舍,开始觉得宿舍挺好的,起码还有自己的桌子,还有插头。。。然后收拾了半天之后发现没有网,然后就觉得笔记本带的多余了。。。然后去看了开幕式,最后抽奖竟然还抽到了我,给了一个8G的小U盘,听说去年的是ipad,真是感动。。。晚上回宿舍之后还好,等十一点多的时候突然灯灭了,后来...
阅读全文