摘要:简单带权并查集0,1关系//#pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;typedef long long ll;typedef pair pii;#define pb(a) push_back(a)#define INF 0x1f1f1f1f#de
阅读全文
摘要:为了方便,记从右到左运输的为A矿,从下到上运输的为B矿。首先,假如我们在第i行的前k格架了运输管道运输这K个格子的A矿,那么对于i下面的其他行最少都能架上k格管子,因为不架也是浪费,这一片区域的B矿已经不可能运输了,都被i行的管道挡住了。基于这点,当第i行前K格用来运输A矿时,剩下的第K+1,K+2...M格就能用来运输B矿,因为上面不会被挡着。dp[i][j]表示第i行,且前面最长的A型管(左右型)为j的状态。则dp[i][j]=max(dp[i+1][k]+f[i][k+1],j#include#include#include#include#include#include#include
阅读全文
摘要:YY过程:概率大的应该先访问吧,嗯,排序一下试试。然后就AC了。。。我也不知道怎么证明这样贪心是正确。。至于DP的过程就是水题了,DP[i][j]表示从第i个开始,分成j组的最小期望//#pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;typedef lo
阅读全文
摘要:用优先队列代替普通队列,这是不是叫权值优先搜索?注意的是与普通队列不同,需要在进队后马上标记,不能等到访问结点的时候再标记,避免多次进队导致复杂度太高。而普通队列是无所谓的。// #pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;typedef long
阅读全文
摘要:// #pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;typedef long long ll;typedef pair pii;#define pb(a) push_back(a)#define INF 0x1f1f1f1f#define lson i
阅读全文
摘要:先不考虑反弹的问题,假设平面是有无数个5*10的矩形组成的,那么子弹最终会停在某个矩形之中而虚拟的子弹在这个矩形中的位置和真实的子弹在原矩形中的位置明显是有关系的,至于什么关系只要这个虚拟的子弹穿过了几次边界就行了每穿过偶次数左(或右)边界,子弹的相对位置是一样的,奇数次的话就是对称,上边界同理。//#pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#include#include#include#include#include#include#include#inc
阅读全文
摘要:七个for。或者写成DP。//#pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;typedef long long ll;typedef pair pii;#define pb(a) push_back(a)#define INF 0x1f1f1f1f#d
阅读全文
摘要:用next_permutation枚举排列//#pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;typedef long long ll;typedef pair pii;#define pb(a) push_back(a)#define INF 0x1f
阅读全文
摘要:换一个方向,将每一个时间点的人加进同一个集合//#pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;typedef long long ll;typedef pair pii;#define pb(a) push_back(a)#define INF 0x1
阅读全文
摘要:数据量这么小,怎么写都行。。枚举每一个为‘.'的格子,从这个格子开始搜索能到达的数字格子,两个格子交换一下,判断连成几个,再交换回来,继续搜索下一个。。//#pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;typedef long long ll;
阅读全文
摘要:用-1表示’(‘,1表示’)‘,那么一个区间合法的充要条件就是最大前缀和最小后缀都为0为了维护这两个值,还需要维护多三个:区间和,最小前缀,最大后缀。见(Merge函数)//#pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;typedef long lon
阅读全文
摘要:分用三次约瑟夫环数学方法就行了。具体见http://www.cnblogs.com/BMan/p/3249094.html //#pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;typedef long long ll;typedef pair pii;#
阅读全文
摘要:结点记录的信息:lics:区间lics的大小lv、rv:区间左右端点的值lpart:以左端点为起点的ics的大小rpart:以右端点为终点的ics的大小//#pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;typedef long long ll;type
阅读全文
摘要:题意:许多条线段首尾相连(初始都在y轴上,第一条线段的一个端点在(0,0)),每一次操作可以将两条相邻线段间的夹角置为a度,输出每次操作后最后一条线段的端点坐标。例如s是线段AB,s+1是线段BC,那么就是要把角ABC置为a度(逆时针方向)。把每条线段都看成一个向量,则最后的端点就是全部向量的和,每次更新就把[s+1,n]之间的向量旋转某个角度b。这个角度b可以由目前s的角度,s+1的角度,输入的a这三个量得到。向量的旋转则是左乘一个旋转矩阵就行了。线段树结点维护两个信息这个区间的向量和、旋转度数//#pragma comment(linker, "/STACK:1024000000
阅读全文
摘要:sum[i]为前缀和对于以i结尾的一段满足要求的最大和则为x=sum[i]-sum[j-1],i-j+1#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;typedef long long ll;typedef pair pii;#define pb(a) push_back(a)#define INF 0x1f1f1f1f#define lson idx T min(const T& a,
阅读全文
摘要:题意O(-1)不用解释。。线段树结点维护三个信息:区间内相同的数出现最多的次数maxc、区间左边第一个数出现的次数lc、区间右边第一个数出现的次数rc。分左区间右端点和右区间左端点相同于否的情况合并区间,注意lc或rc为区间长度的情况。 //#pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#include#include#include#include#include#include#include#include#include#include#includeus
阅读全文
摘要:状态DP,设S为当前已经获得的武器的集合,预处理全部S能攻击的集合g[S]。后面的状态转移就是dp[st]=sum{dp[st^(1<<i)] | i为st的元素,且i为个g[st^(1<<i)]的元素}ll dp[1<<16];int g[1<<16];int n;int p[20];int read(){ char s[20][20]; scanf("%d",&n); for(int i=0;i<=n;i++) scanf("%s",s[i]); for(int i=0;i<=n;i
阅读全文
摘要:题意:给一个正整数k和字符串s,s的长度是k的倍数,把s每k个字符分成一组,没组之间的字符可以任意重排,但组与组之间的顺序保持不变。任务是让重排后的新字符串s'的块最少,连续相同的字符组成一个块,比如abbbaa有三个块a、bbb、aa。首先每一组子串中相同的字符肯定要放在一起,然后问题就变成怎么排列这些子串中的块。用dp[i][fa]表示前i组且第i+1组的最左边的字符是fa+'a'的状态能得到的最少的块数那么状态的转移就是两层循环枚举这个第i组最左边和最右边应该放上什么字符,如果最右边和前一组的最左边一样,那么总块数就是加上(X-1)否则加上X,X表示这一组中字符的
阅读全文
摘要:题意:求一个波浪子序列,就是是前一半是上升子序列,后一半是下降子序列(子序列的长度必须为奇数)。分别从左右两个方向求LIS,然后在统计最大值就行了 //#pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;typedef long long ll;typede
阅读全文
摘要:题意:给一个无向连通图,和一个长度为L的序列。任务是修改序列上的某些数使得每相邻两个数相等或在图上是两个相邻的点。最少需要修改几个数?用dp[n][fa]表示当第n+1个数是fa时前n个数最少要修改几次用邻接矩阵存图,补上g[i][i]=1;g[0][i]=1;就可以不用分别考虑相等和初始的状态了dp[n][fa]=min{dp[n-1][v]+(v==an?0:1) | g[fa][v]==1}int g[110][110];int da[210];int dp[210][110];int f(int n,int fa,int N){ if(dp[n][fa]>=0)return dp
阅读全文
摘要:题意:是否能经过若干次切割把一块x*y的长方形巧克力分成n块,每块是a1,a2,a3...an小块st表示{a1,a2,...an}的某个子集。先预处理出全部sum[st],各个子集的小块总数dp[l][st]表示长为l,宽为sum[st]/l的长方形能否被分成子集st.因为面积必须相等才有可能具体的状态转移看代码int da[16];int sum[10) { if(k%2==1) { sum[st]+=da[bit]; } k/=2;bit++; ...
阅读全文
摘要:题意:有n个垃圾,坐标为(xi,yi)重量为wi。有一个机器人,要按照编号从小到大的顺序捡起所有垃圾并扔进垃圾桶(坐标(0,0))。机器人可以捡起几个垃圾以后一起扔掉,但任何时候其手中的垃圾总重量不能超过C.两点间的行走距离为曼哈顿距离。求出机器人行走的最短距离。设dp[i]为机器人清理完前i个垃圾所走的最短路程,则,dp[i]=min{dp[j]+dist(0,j+1)+dist(j+1,j+2)+dist(j+2,j+3)...+dist(i-1,i) + dist(i,0) | jfront&&totalw[i]-totalw[q[front]]>c)front++
阅读全文
摘要:题意:给一个n个点m条边的无向无环图,再尽量少的结点上放上灯,使得所有边都被照亮(每个灯会照亮所有与它相连的边)在灯的总数最小的前提下,被两盏灯照亮的边尽量大。优化条件有两个:灯的数量a最少,被两灯照亮的边数b最大,因为边的总数是一定的,不是被一个灯照亮就是被两个灯照亮所以第二个条件可用"被一个灯照亮的边数c最小"代替设x=a*M+c;M是一个足够大的常数那么优化条件就变成只有x尽量小了,决定x大小的主要是a的值,在a的值相同的情况下才考虑c的值最终求到x后,a=x/M,c=x%M,b=m-c;dp[i][j]表示以结点i为跟的子树的最优解,j为父节点的放灯状态,j=0表示
阅读全文
摘要:题意:有一个由编号0~n-1的n台计算机组成的网络,一共有n种服务,每台计算机上都运行着全部服务,对于每台计算机,你可以选择停止一项服务,这个行为会导致与这台计算机和与他相连的其他计算机上的这项服务都停止(原来已经停止的继续保持停止状态)。求最多能使多少个服务瘫痪(即没有任何一台计算机在运行这项服务)。首先是一个枚举子集的技巧for(int sub=S;sub>0;sub=(sub-1)&S)问题抽象成数学模型就是:把n个集合p[i],00;sub=(sub-1)&st)if(c[sub]==total) { dp[st]=max(dp[st...
阅读全文
摘要:题意:给n个数,A,B两人轮流取,每次可从左右其中一边取1或多个数,两个人都尽量使自己取的数总和最大,问最终sumA-sumB最大为多少。由于两个人取的数总和是一定的,所以只要求出先取的那个最多有多少就行了。用dp[i][j]表示a[i..j]这一段数中先取的人能取到的最大和。(这里的先取意思是表示这在一段先取,不是A的意思)先取的人可能取左边任意一段a[i..i],a[i..i+1],a[i...i+2]....a[i,j]或右边任意一段a[j...j],a[j-1...j],a[j-2..j]....a[i,j]那么另一个人就有可能从a[i+1...j]、a[i+2....j],a[j..
阅读全文
摘要:题意:求最长公共子序列正常的算法O(n^2)不够快,但因为这题数据特殊,数组中的数各不相同,可以转化成求最大上升子序列比如样例中A{1 7 5 4 8 3 9}, B{1 4 3 5 6 2 8 9},将数字重新映射编号map[ai]=i;ai=map[ai];bi=map[bi];变成A{1,2,3,4,5,6,7} B{1,4,6,3,0,0,5,7} 问题便变成了求B的LIS可以在0(nlogn)求出// #pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#in
阅读全文
摘要:题意:n个人围成环,首先第m个人出列,然后从下一个开始,数到第k个就出列。。。问最后剩下的是谁?为了方便,我们采用0~n-1的编号方式先考虑当题意没有m的时候,就是说从第一个人开始,第k个人出列。那么第一个出列的就是编号k-1的人,此时我们把剩下的人重新编号k->0k+1->1k+2->2........k-2->n-2假设新编号为x的人是最终剩下来的,那他在原来的编号是多少?就是(x+k)%n所以我们只要一直重复这个过程便能求得最开始那个人的编号,因为这个人最终的编号是0(只剩他一个人)0->(0+k)%2->((0+k)%2+k)%3->.....
阅读全文
摘要:题意:给你一个正长方体,长宽高分别为n、m、k,这个长方体由n*m*k个1*1*1的小立方体组成把这些小立方体编号为0-(n*m*k-1),再给l个编号,表示这些小立方体是存在的,否则就是不存在的求最总整个图形的外表面积解题思路:首先解决坐标与编号的转换,用0开始标号,比用1方便很多,跟二维数组差不多,很轻松就可以推出坐标转编号:id=z*(m*n)+y*n+x;编号转坐标: z=id/(n*m); id-=z*(m*n); y=id/n; x=id%n;上面写成两个函数备用首先想到,以其中一个存在的小立方体开始,往上下左右前后六个方向搜索,如果这个方向上有小方块,就转移到这个小方块上继续搜索
阅读全文
摘要:问题抽象成数学概念就是:给你n条线段,问最少需要分成几组,使得每组中的线段互不相交贪心:把线段按左端点排序,对于每一组,我们用一个变量t记录这组里面的线段中的最大的右端点对于每一条线段,我们找到t最大且#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;typedef long long ll;typedef pair pii;#define pb(a) push_back(a)#define INF
阅读全文
摘要:题意:我们把1-n这n个数的某个排列摆成一排,然后相邻两个数的和放到下一行,依此类推,形成一个三角形3 1 2 4 43 6 7 916给你n和最终得到的和k,求第一行的系列(字典序最小)我们可以发现每个数字的计算次数是一个杨辉三角1 1 1 2 1 1 3 31 1 4 6 4 1 ......所以我们只要枚举1-n的全排列,计算sum{ans[i]*c(i-1,n-1)}是否为K就行了当然从顶层一步一步算到最低也是一样的10!为380W,而且因为左右对称,规模能减一半枚举全排序能用STL中的next_permutation能很方便的求出如果不知道这个函数,就写个DFS //#pragma
阅读全文
摘要:题意:M个陨石会在某个时间砸向地图某点,摧毁该点及其上下左右总共五个格子,也就是在这个时间以后这些格子就不能通过了,问主人公从(0,0)开始最少需要多少时间能到达安全的地方(也就是一直不会被摧毁的地方)此题有个小陷阱,with meteoriwill striking point (Xi,Yi) (0 ≤Xi≤ 300; 0 ≤Yi≤ 300) at timeTi(0 ≤Ti ≤ 1,000). 这里的X、Y指的是陨石的范围而不是地图的范围,地图是一张无限大的,也就是可以走到300以外地方。先初始化所以格子的崩塌时间为INF(无限大),然后预处理出所有的时间,再跑一遍BFS就行了// #pra
阅读全文
摘要:简单DFS注意边界就行了。// #pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;typedef long long ll;typedef pair pii;#define pb(a) push_back(a)#define INF 0x1f1f1f1f#
阅读全文
摘要:今天开始用cnblogs记录题解,与网易分开。没办法,能折叠代码就找到这个。没心情切题,把开始集训以来的题解补上。
阅读全文