08 2013 档案
摘要:#include#include#include#include#include#include#include#include#include#include#include#define Maxn 1010#define Maxm 100010#define LL __int64#define Abs(x) ((x)>0?(x):(-x))#define lson(x) (x<<1)#define rson(x) (x<<1|1)#define inf 0x7fffffff#define Mod 1000000007using namespace std;in
阅读全文
摘要:思路:每次合并时,都是给一个虚拟的根。#include#include#include#include#include#include#include#include#include#include#include#define Maxn 100010#define Maxm 2000010#define LL __int64#define Abs(x) ((x)>0?(x):(-x))#define lson(x) (x<<1)#define rson(x) (x<<1|1)#define inf 0x3f3f3f3f#define Mod 1000000007
阅读全文
摘要:#include#include#include#include#include#include#include#include#include#include#include#define Maxn 52#define Maxm 100010#define LL __int64#define Abs(x) ((x)>0?(x):(-x))#define lson(x) (xb?b:a;}int solve(){ int i,j,r,ki,kj,fi,fj,N; N=(1<<k)-1; dp[0][1][0]=0; for(ki=0;ki<=N;ki++){ ...
阅读全文
摘要:思路:其实就是让每一条路有尽量多的人走。#pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#include#include#include#include#include#include#include#include#define Maxn 100010#define Maxm 100010#define LL __int64#define Abs(x) ((x)>0?(x):(-x))#define lson(x) (x<<1)#define r
阅读全文
摘要:思路:将每个回合的平手和赢最为一对对立状态。那么后面就是2-SAT判断了。#include#include#include#include#include#include#define Maxn 20010using namespace std;map g[Maxn];int vi[Maxn],head[Maxn],dfn[Maxn],low[Maxn],e,n,lab,top,num,id[Maxn],Stack[Maxn],wh[Maxn],hh[4][4];struct Edge{ int u,v,next;}edge[100000];void init()//初始化{ me...
阅读全文
摘要:思路:这里必须要选择的点是2*k个,首先就是求一边斯坦纳树,然后做一次动态规划出每个状态下的最小值。#include#include#include#include#include#include#include#include#include#include#include#define Maxn 210#define Maxm 100010#define LL __int64#define Abs(x) ((x)>0?(x):(-x))#define lson(x) (x>=1) res+=(s&1)*(i=inf) printf("No solution\n
阅读全文
摘要:思路:虚拟一个0号节点,将每个点建一条到0号节点的边,权值为挖井需要的价值。并要保证0号节点同另外n个寺庙一样被选择即可。然后就是求斯坦纳树了。#include#include#include#include#include#include#include#include#include#include#include#define Maxn 1310#define Maxm 100010#define LL __int64#define Abs(x) ((x)>0?(x):(-x))#define lson(x) (x q; dis[i][i]=0; q.push...
阅读全文
摘要:思路:直接先求一下最小生成树,然后用树形dp来求最优值。也就是两遍dfs。#include#include#include#include#include#define Maxn 2010using namespace std;struct Edge{ int u,v; double c; int operator Max[u]){ lMax[u]=Max[u]; Max[u]=Max[v]; road[u]=v; } else if(Max[v]>lMax[u]){ ...
阅读全文
摘要:思路:将边从大到小排序,判断向哪边连,能使总和最大。#include#include#include#include#include#include#include#include#include#include#include#define Maxn 200010#define Maxm 200010#define LL __int64#define Abs(x) ((x)>0?(x):(-x))#define lson(x) (xtemp.val; }}p[Maxn];int Set[Maxn];LL sum[Maxn],num[Maxn];int Find(int x){ i...
阅读全文
摘要:思路:直接状态压缩暴力枚举#include#include#include#include#define Maxn 30#define inf 10000000using namespace std;int ans,n,m;int c,d;int map[Maxn][Maxn];int lis[Maxn],node[Maxn];int val[1m) continue; if(cnt==m) { int a=val[i],b=sum[i]; if(a*d<c*b){ ...
阅读全文
摘要:思路:黑书的例题#include#include#include#include#include#define Maxn 210using namespace std;int dp[Maxn][Maxn][Maxn],col[Maxn],len[Maxn],pre[Maxn],aper[Maxn],after[Maxn],vi[Maxn];int main(){ int t,n,i,j,x,k,Case=0; int cnt=0; scanf("%d",&t); while(t--){ memset(dp,0,sizeof(dp)); mem...
阅读全文
摘要:思路:裸的2-SAT。#include#include#include#include#include#include#include#include#include#include#include#define Maxn 2010#define Maxm 100010#define LL __int64#define Abs(x) ((x)>0?(x):(-x))#define lson(x) (x head[Maxn];void init(){ memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); lab=num=to...
阅读全文
摘要:思路:定义一个四维状态的数组,记录每个状态先手的最优值。#include#include#include#include#include#define Maxn 30using namespace std;int ans[Maxn][Maxn][Maxn][Maxn],suma[Maxn],sumb[Maxn];void init(){ memset(ans,0,sizeof(ans)); memset(suma,0,sizeof(suma)); memset(sumb,0,sizeof(sumb));}inline int Max(int a,int b,int c,int...
阅读全文
摘要:思路:这题我在下午重现的时候就用的费用流做,可是各种悲催的超时,只是我一开始的那种建图方式多了一个二分查找。戏剧性的是,求距离的返回值写成int型了,CodeBlock编译器又没有警告,然后就WA啊WA,AC率一下就被拉低了。当然,对每种工人分别建图是不变的,因为每种工人互不影响。后来想到了一个较好的建图方式,将每个点拆成3个点,i,i+n,i+2*n。1号点就是仓库,也就是超级源点,3*n+1号点为超级汇点。由1号点想每个i建一条流量为ty[i][j],费用为1的边。表示每次增加流量,人数就增加。由i向i+2*n建一条流量为ty[i][j],费用为0的边。由i+2*n向汇点建一条流量为ty[
阅读全文
摘要:思路:首先就是判断是否有奇环,若存在奇环,则输出No。然后用差分约束找是否符合条件。对于e(i,j)属于E,并且假设顶点v[i]为正数,那么v[i]-v[j]>=T--->v[j]-v[i]#include#include#include#include#define Maxn 1010#define Maxm Maxn*Maxn#define inf 100000000#define T 400using namespace std;int head[Maxn],vi[Maxn],col[Maxn],map[Maxn][Maxn],e,n,cnt[Maxn],dis[Maxn];
阅读全文
摘要:思路:以val[u]-ans*edge[i].len最为边权,判断是否有正环存在,若有,那么就是ans小了。否则就是大了。在spfa判环时,先将所有点进队列。#include#include#include#include#include#include#define Maxn 1010#define Maxm 6000#define inf 1e10#define eps 1e-4using namespace std;int vi[Maxn];struct Edge{ int u,v,next; double len;}edge[Maxm];double dis[Maxn],v...
阅读全文
摘要:思路:和黑书上的跳舞机类似#include#include#include#include#include#include#include#include#include#include#include#define Maxn 31#define Maxm 100010#define LL __int64#define Abs(x) ((x)>0?(x):(-x))#define lson(x) (x<<1)#define rson(x) (x<<1|1)#define inf 0x7fffffff#define Mod 1000000007using names
阅读全文
摘要:思路:黑书的例题#include#include#include#include#include#include#include#include#include#include#include#define Maxn 110#define Maxm 100010#define LL __int64#define Abs(x) ((x)>0?(x):(-x))#define lson(x) (x<<1)#define rson(x) (x<<1|1)#define inf 0x7fffffff#define Mod 1000000007using namespace
阅读全文
摘要:思路:枚举能是A,B,C在一条简单路径上的中点。 计算多少个几何能满足。在用总数减去#pragma comment(linker, "/STACK:16777216")#include#include#include#include#include#include#include#include#include#include#include#define Maxn 200010#define Maxm 300010#define LL __int64#define Abs(x) ((x)>0?(x):(-x))#define lson(x) (x son[Maxn]
阅读全文
摘要:思路:主要就是模拟这些操作,用链表果断超时。改用堆栈模拟就过了#include#include#include#include#include#include#include#include#include#include#include#include#define Maxn 1000010#define Maxm 300010#define LL __int64#define Abs(x) ((x)>0?(x):(-x))#define lson(x) (x br,af;int main(){ int i,j,u,v,n,x; char str[3]; int brz,a...
阅读全文
摘要:思路:用map将每个字符串与一个数字进行对应,然后暴力统计就好了#include#include#include#include#include#include#include#include#define Maxn 2010using namespace std;int fr[Maxn][Maxn],mul[Maxn][Maxn],Max[Maxn];char str[Maxn][20];map g;vector head[Maxn*2];vector ans[Maxn*2];int cmp(int a,int b){ return strcmp(str[a],str[b])<0;}i
阅读全文
摘要:思路:dp[i][x][y]表示第i个序列中,右脚在x位置,左脚在y位置时,其最小花费。那么dp[i][x][y]=min(dp[i-1][a[i]][y]+cost[a[i]][x],dp[i-1][x][a[i]]+cost[a[i]][y]);题目连接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=32#include#include#include#include#include#include#incl
阅读全文
摘要:思路:黑书的例题#include#include#include#include#include#define Maxn 20#define mul(a) ((a)*(a))using namespace std;int dp[16][9][9][9][9];int s[10][10],val[10][10];int S(int x1,int y1,int x2,int y2){ return mul(s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1]);}int main(){ int n,m,i,j; double avg; ...
阅读全文
摘要:思路:黑书的例题#include#include#include#include#define Maxn 1010using namespace std;int dp[Maxn][Maxn],v[Maxn][Maxn];char str[Maxn];void Out(int s,int e){ if(s>e) return ; if(s==e) { if(str[s-1]=='('||str[s-1]==')') printf("()"); else printf("[]"); ...
阅读全文
摘要:思路:就是个比较裸的LCA了,不过要注意的是,如果a和b的公共祖先是a,那么答案就是farther[a]。#include#include#include#include#include#include#include#include#define Maxn 300010using namespace std;int vi[Maxn],pre[Maxn];int dep[Maxn],sec[Maxn],farther[Maxn];int e,Md;char str[Maxn][70],ans[Maxn][70];vector head[Maxn];map g;void init(){ M...
阅读全文
摘要:思路:分等号左边和右边进行搜索#include#include#include#include#include#define LL __int64using namespace std;char str[20];int n,ans;void right(LL sum,LL now,int cnt){ if(cnt==n) { if(sum==now) ans++; return ; } if(sum==0) return ; if(sum>=now*10+(LL)(str[cnt]-'0')) ...
阅读全文
摘要:思路:考的是字符串的编辑距离。在蓝桥杯2012年决赛上出现过。#include#include#includeusing namespace std;int dp[200050][20];char targ[20],ans;int Min(int a,int b,int c){ int temp; temp=a0) strcpy(targ,str2); } else { strcpy(targ,str2); ans=t;...
阅读全文
摘要:思路:这题和1227的求法一样,只不过1227是小数据,暴力下,就能进行预处理。这题的预处理区间期望cost[i][j]需要利用单调性。即假使以pos位置为安排的点,那么这个区间在其左边的概率为l,右边的概率为r,总期望为sum。如果将安排点从pos放到pos-1该区间增加的期望为r*(p[pos].x-p[pos-1].x)减少的期望为l*(p[pos].x-p[pos-1].x)如果减少的超过增加的,那么pos-1就比pos好。#include#include#include#include#include#define Maxn 1010using namespace std;doubl
阅读全文
摘要:思路:主要就是要把一个每个城市拆为两个点,建一条容量为1,费用为-inf的边,保证每个城市都会被遍历。/*最小费用最大流*/#include#include#include#include#includeusing namespace std;const int Maxn = 1010;const int inf = 1000010;struct Edge{ int v; int val; int cost; int next;}edge[Maxn*100];int head[Maxn],n,g[Maxn][Maxn],m,k;int e;int pre[Maxn], ...
阅读全文
摘要:思路:我们其实只需要枚举每条边,求得最小值就行了。先dfs算出每个节点作为根时,其子树的最长路径,以及进过该节点的最长,次长,第三长路径。然后在次dfs枚举求出切断某条边,求出这条边的两个端点为子树根,其子树的最长路径。b就是其中较大的。#pragma comment(linker, "/STACK:1024000000,1024000000")#include#include#include#include#include#include#define Maxn 200010using namespace std;int road[Maxn],Max[Maxn],lMax
阅读全文
摘要:思路:首先看到这题以为能用poj1904的模版直接A掉,WA了几次,然后又TLE了几次。还是想到了正解。一开始我想的大致方向已经是对的了。先是由王子向每个喜欢的公主建边,再求一次最大匹配,找出匹配后,由匹配的公主向王子建边。但可能会有没有匹配到的公主和王子,那么这个王子可以和任何它喜欢的公主结婚,这个公主也可以和任何喜欢她的王子结婚。因为这些不在匹配中的点,加到匹配中后,减少的匹配数和增加的匹配数都是1。我们也就想像poj1904那样,将他们变为一个强连通分量,我开始出错就在这。直接在原图上将他们建边变为强连通分量会使原图性质发生改变。所有我们对每个没有匹配的公主,建一个虚拟的王子,让他们变成
阅读全文
摘要:思路:首先当然是要用树的点分治了。根节点为root,那么经过root的合法路径数求出来这题就解决了。因为我们可以用分治枚举根,最后将所有根的路径数加起来就是结果。当然这里的根不是整棵树的根,是子树根。我们为每个节点分配一个长度为30的数组记录给定因数在每个节点权值出现的次数。如果某几个权值相乘的值Value的三次根仍是整数的话,那么Value在给定因数的所有幂一定是3的倍数。通过这个转换,我们将所有的幂都对3取余,结果还是一样。在判断经过root的合法路径数时,我们进入其一个子树,将经过的路径因数的幂相加,判读其是否有对立状态存在,若存在,结果+1。所谓对立状态就是能够合成合法路径的状态。例如
阅读全文
摘要:思路:1741的A1送 1.#include#include#include#include#include#define Maxn 40010#define Maxm 80010#define inf 0x7fffffffusing namespace std;int head[Maxn],vi[Maxn],e,ans,num,k,n,m;int mx[Maxn],mi,dis[Maxn],root,size[Maxn];struct Edge{ int u,v,val,next;}edge[Maxm];void init(){ memset(vi,0,sizeof(vi)); ...
阅读全文
摘要:思路:这题我是看 漆子超《分治算法在树的路径问题中的应用》写的。附代码:#include#include#include#include#include#define Maxn 10010#define Maxm 20010#define inf 0x7fffffffusing namespace std;int head[Maxn],vi[Maxn],e,ans,num,k,n;int mx[Maxn],mi,dis[Maxn],root,size[Maxn];struct Edge{ int u,v,val,next;}edge[Maxm];void init(){ memse...
阅读全文
摘要:思路:主要就是一个动态方程dp[now][(j*Exp[len[num[i]]]+num[i])%k]+=dp[pre][j];我用的是滚动数组。其实也就是dp[i][(j*Exp[len[num[i]]]+num[i])%k]+=dp[i-1][j];唯一需要注意的就是存在长度长于n的串,要减掉。#include#include#include#include#define Maxn 100010using namespace std;int len[Maxn],Exp[Maxn*3],n,k,num[Maxn];int dp[3][210];void init(){ int i; ...
阅读全文
摘要:思路:这题我是看了题目后,上百度搜了一下才知道还有求最大曼哈顿距离的方法。直接把代码copy过来,研读一下,知道了代码实现机制,自然就很容易想到用优先队列来维护每种状态下的xi,yi之和的最大值最小值,以及其属于哪个点。那么对于删点操作只需要标记为不存在就可以了。在队列出队时,若队顶元素不存在,就出队。#include #include #include #include #include #include #include #include using namespace std;const int Maxn=100005;const int inf=0x7fffffff;struct Qu
阅读全文
摘要:题意:每个用户对数据库的查询请求都会首先用该数据库的服务器序列的第一个去执行任务,若第一个坏了,就由第二个执行。最多只会坏一个服务器。要求是考虑最多坏一个的情况下,所有服务器中执行用户查询的数目最大值与最小值之差不能超过1。思路:对于n>=m的情况,很容易能解决掉,关键是n#include#include#include#includeusing namespace std;int ans[110][3],pre[110],vi[110],num[110],n,m;struct Que{ int val,c; int operator temp.c; }};int Ok(){...
阅读全文
摘要:思路:首先声明我是参考:http://blog.csdn.net/frog1902/article/details/9921845这位大牛的博客的。他说的已经很详尽,但我还是要补充几点。看完他的解题报告在看我的才好些。我这的back[i]对于他的lim[i]。我要补充的是,back[i]不是真正的back[i],可以看到这行代码:back[u]=max(back[u],dep[v]+1);也就是说是其返回祖节点再往下的一个节点。对于没有回退边的点,其back[i]==0相当于有一个回退边到根节点,那么本节点到根节点上的任何一条边被选择都是可行的。dp时,首先将dp[u][i](back[u]#
阅读全文
摘要:思路:用sum[i]表示区间长度为i的不相同数的个数和,假使所有的数都不相同,那么sum[i]=sum[i-1]+n-i+1-later[i-1]; later[i-1]表示的是序列最后面的长度为i-1的序列不同数的个数。这个式子的意义是每个长度为i-1的序列扩展为长度为i的序列,其不同数的个数会加1,一共有n-i+1个长度为i-1的序列能扩展,因为最后面的一个长度为i-1的序列肯定是扩展不了的(后面没数了),故要将最后面的长度为i-1的序列减去,即减later[i-1]。那么对存在相同数的情况就是,任何数x,如果距离其上次出现的位置小于等于i-1,那么在n-i+1的基础上就要减去1。但这个并
阅读全文
摘要:思路:裸的划分树#include#include#include#include#include#define Maxn 100010#define lson(x) x>1; }}tree[Maxn*4];void BuildTree(int l,int r,int dep,int po){ tree[po].l=l,tree[po].r=r; if(l==r) return ; int mid=tree[po].mid(); int lpos=l,rpos=mid+1; int same=mid-l+1,i; for(i=l;isort...
阅读全文
摘要:思路:这题是裸的树形dp。dp[i][j]表示第i个节点花费j步并且从子节点返回,能得到的最大苹果数;nback[i[j]表示第i个节点花费j步并且进入某个子节点不返回,能得到的最大苹果数。那么我们就能得到动态方程:根节点为u,子节点为vdp[u][j]=max(dp[u][j],dp[u][j-k-2]+dp[v][k]);nback[u][j]=Max(nback[u][j],nback[u][j-k-2]+dp[v][k],dp[u][j-k-1]+nback[v][k]);//表示对某个节点可以选择进入返回或不返回.#include#include#include#include#in
阅读全文
摘要:思路:表示我很弱,这个想不出dp方程,参考网上代码#include#include#include#include#include#include#define inf 1 head[Maxn];void init(){ memset(dp,0,sizeof(dp)); memset(vi,0,sizeof(vi)); for(int i=0;i=inf) printf("-1\n"); else printf("%d\n",dp[1][0]); } return 0;}
阅读全文
摘要:思路:本来写了一个比较短的代码,并且各函数间的重用性比较高,就是结果悲剧的超时了...就是保证每个区间只有一种操作,那么更新时就要更新子节点的子节点,需要递归更新,结果是可想而知。其实这种做法是可以过得,只要将复杂度转移到求和上去(测试数据对求和操作应该要求不严)。但那样就不能直接保存p的三种情况值,因为这样会使得常数级非常大,超时。所以就要找到多重操作并存的方法。对于置为c,这个容易解决。关键是加和乘。思路见代码注释#include#include#include#include#include#define lson(x) x>1; }}tree[Maxn*4];int ans;vo
阅读全文
摘要:#include#include#include#include#include#define Maxn 100010using namespace std;struct Monk{ int id,g; int operator q;multiset :: iterator it,it1;int main(){ int n,i,j,g,k,x; Monk temp; while(scanf("%d",&n),n) { q.clear(); temp.id=1,temp.g=1000000000; q.insert(...
阅读全文
摘要:思路:对于最大的人数很容易想到,就直接dp。但对于最大值是否唯一就需要应用辅助数组,isOnly[i][0]表示dp[i][0]是否唯一,同理isOnly[i][1]。那么当(dp[v][0]>dp[v][1]&&isOnly[v][0]==0)或(dp[v][1]>dp[v][0]&&isOnly[v][1]==0)或(dp[v][1]==dp[v][0]),那么isOnly[u][0]=0;如果isOnly[v][0]==0,那么isOnly[u][1]=0;#include#include#include#include#include#inc
阅读全文
摘要:思路:先dfs一下,找出1,n间的路径长度和价值,回溯时将该路径长度和价值清零。那么对剩下的图就可以直接树形dp求解了。#include#include#include#include#define inf 100000000#define Maxn 110using namespace std;int vi[Maxn],head[Maxn],dp[Maxn][510],e,n,T,a[Maxn],len,sum;struct Edge{ int u,v,next,val;}edge[Maxn*2];void init(){ memset(vi,0,sizeof(vi)); ...
阅读全文
摘要:思路:先求以1为根时,每个节点到子节点的最大长度。然后再次从1进入进行更新。#include#include#include#include#include#define Maxn 20010#define inf 0x7fffffffusing namespace std;int vi[Maxn],si[Maxn],n,road[Maxn],Max[Maxn],lMax[Maxn],head[Maxn],e;struct Edge{ int u,v,val,next;}edge[Maxn*2];void init(){ memset(vi,0,sizeof(vi)); me...
阅读全文
摘要:思路:裸的划分树#include#include#include#include#include#define Maxn 100010#define lson(x) x>1)using namespace std;int val[20][Maxn],toLeft[20][Maxn],sorted[Maxn];struct Tree{ int l,r;}tree[Maxn*4];void BuildTree(int l,int r,int dep,int po){ tree[po].l=l,tree[po].r=r; if(l==r) return ; in...
阅读全文
摘要:思路:裸的划分树#include#include#include#include#include#include#define Maxn 100010#define inf 0x7fffffff#define lson(x) (x>1)using namespace std;struct Tree{ int l,r;}tree[Maxn*4];int sorted[Maxn];int val[20][Maxn],toLeft[20][Maxn];void BuildTree(int l,int r,int dep,int po){ tree[po].l=l,tree[po].r=r...
阅读全文
摘要:思路:用Sum[dep][i]记录从tree[po].l到i中进入左子树的和。#include#include#include#include#include#include#define Maxn 100010#define inf 0x7fffffff#define lowbit(x) (x&(-x))#define lson(x) (x>1)using namespace std;struct Tree{ int l,r;}tree[Maxn*4];__int64 Sum[20][Maxn],sum[Maxn];__int64 lnum,lsum;int sorted[Ma
阅读全文
摘要:思路:二分枚举区间第k大。用划分树查找是否符合要求的高度。#include#include#include#include#include#define Maxn 100010#define lson(x) x>1)using namespace std;int val[20][Maxn],toLeft[20][Maxn],sorted[Maxn];struct Tree{ int l,r;}tree[Maxn*4];void BuildTree(int l,int r,int dep,int po){ tree[po].l=l,tree[po].r=r; if(l==r) ...
阅读全文
摘要:思路:直接搜索#include#include#include#includeusing namespace std;int belong[5010],num[5010],n;int dfs(int s,int pre,int cur){ int i,j; if(cur==n/2) return 1; for(i=s;ipre) { belong[j]=1; if(dfs(s+1,j,cur+1)) return 1; ...
阅读全文
摘要:思路:我们定义两个数组,ant[Maxn][2],bob[Maxn][2]。ant[i][0]表示还未确定哪个城市被全费用占领,ant[i][1]表示确定了哪个城市被全费用占领。那么ant[i][0]的转移方程是ant[u][0]+=min(ant[v][0],bob[v][1]);即与它相连的那个城市也未确定全费用占领的城市,或者被bob占领,且确定了全费用。由于ant[u][0]表示未确定,故不能从ant[v][1]的确定状态转移过来。ant[u][1]=ant[u][0]+min(a[u],m1+a[u]/2);对于u节点确定了全费用占领城市,那么要么就是自己全费用占领,或者是他的某个相
阅读全文
摘要:思路:先将图进行缩点,建成一颗树,那么如果这是一条单路径树(即最大点度不超过2),就不在能删的一条边,使得不连通。因为将其头尾相连,形成一个圈,那么删任意一条边,图都是连通的。上面的是无解的情况,如果有解,那么这个解一定是树中不全在一条路径上的三条边中的一条,使得这三条边中的最大边最小,即得解。同样,对任意一个节点,其三个子树上的边一定是三条不全在一条路径上的边。问题就转化为求一个节点的第三小边。但直接求第三小边容易出错,并且不易求得。我们可以先选一条树中的最小边,这条边一定是三条边中的一条,我们就沿着这条边的两个端点找。那么问题就又变成了求一个节点的次小边了。这个很容易求得。感谢http:/
阅读全文
摘要:思路:我们定义一个dfn[i],Maxndfn[i]来确定节点i的访问次序,以及其子节点的最大访问次序。那么另一个节点是其子树的节点当且仅当dfn[j]>=dfn[i]&&dfn[j]#include#include#include#include#define Maxn 100010#define inf 0x7fffffffusing namespace std;int son[Maxn],nson[Maxn],der[Maxn],nder[Maxn],n,q,dfn[Maxn],Maxdfn[Maxn],lab,dp[Maxn],road[Maxn],father[
阅读全文
摘要:思路:设sum[i],le[i],back[i],worm[i]分别表示以i为根节点需要的完成步数,叶子节点数,失败回退步数,以及i是否有虫。#include#include#include#include#define Maxn 1010using namespace std;int sum[Maxn],worm[Maxn],le[Maxn],vi[Maxn],head[Maxn],e,n,back[Maxn];struct Edge{ int u,v,next;}edge[Maxn*Maxn];void init(){ memset(sum,0,sizeof(sum)); ...
阅读全文
摘要:思路:若没有边权,则对点权从大到小排序即可,考虑边,将边权拆成两半加到它所关联的两个点的点权中即可,因为当两个人分别选择不同的点时,这一权值将互相抵消。#include#include#include#includeusing namespace std;double val[100010];int cmp(double a,double b){ return a>b;}int main(){ int n,i,m,j,a,b; double c; while(scanf("%d%d",&n,&m)!=EOF) { for(i=1;i<=n;i++
阅读全文
摘要:思路:定义一个三维数组dp[x][i][j]其中x为now和pre两种状态,now表示当前两行最优解,pre表示出了本行外,前两行的最优解。那么状态转移方程为dp[now][j][k]=max(dp[now][j][k],dp[pre][k][r]+num[i][j][1])。num[i][j][1]表示第i行的第j个状态的1的个数。转移条件是!(num[i][j][0]&num[i-1][k][0])&&!(num[i][j][0]&num[i-2][r][0])&&!(num[i-1][k][0]&num[i-2][r][0])为真。
阅读全文
摘要:思路:将每一行看做一个二进制位,那么所有的合法状态为相邻为1的个数一定要为偶数个。这样就可以先把所有的合法状态找到。由于没一层的合法状态都是一样的,那么可以用一个数组保存。由第i-1行到第i行的状态转移是dp[i][now|num[j]]+=dp[i-1][k],其中now为(1#include#include#include#define Maxn 13#define inf 0x7fffffffusing namespace std;__int64 dp[Maxn][1=1;i--) sum+=graphic[i]*(1<<(m-i)); num[++c...
阅读全文
摘要:思路:把每行的数当做是一个二进制串,0不变,1变或不变,找出所有的合法二进制形式表示的整数,即相邻不同为1,那么第i-1行与第i行的状态转移方程为dp[i][j]+=dp[i-1][k];这个方程得前提条件是num[i][j]&num[i-1][k]==0,也就是他们表示的二进制形式相与为0,那么就不存在相邻为1的情况。#include#include#include#include#define Maxn 13#define inf 0x7fffffffusing namespace std;__int64 dp[Maxn][1=1;i--) sum+=graphic[...
阅读全文
摘要:思路:我只想说,while(head#include#include#include#include#define Maxn 110#define Maxm 10010#define inf 1000000000using namespace std;int dp[Maxn][Maxm],sum[Maxm],num[Maxn][Maxm];int que[Maxm*5];void init(){ memset(sum,0,sizeof(sum)); memset(num,0,sizeof(num));}inline int ReadInt(){ int flag = 1; ...
阅读全文
摘要:思路:动态方程很容易想到dp[i][j]=max(dp[i][j],dp[i-w-1][j-k]-k*ap[i],dp[i-w-1][j+k]+k*bp[i]);dp[i][j]表示第i天拥有j个石头的最大价值。其实每次求得都是最有策略,所有dp[i-w-1]表示的就是i-w-1以前的最优,故不同往前遍历。那么主要需要优化的是:对于买石头,容量为j时,维护从j-k到j的转移最大值。即从哪个容量转移过来能得到最大效益。对于卖石头,容量为j时,维护从j+k到j的转移最大值。即从哪个容量转移过来能得到最大效益。见代码:#include#include#include#include#include#
阅读全文
摘要:思路:我们用单调队列保存2*b#include#include#include#include#define inf 10000010#define Maxn 1010#define Min(a,b) (a)>(b)?(b):(a)using namespace std;int dp[1000010],que[1000010],head,rear,interv[1200010];struct Inter{ int l,r; int operator=inf) printf("-1\n"); else printf("%d\n",dp[l]); }
阅读全文
摘要:思路:如题#include#include#include#include#include#define Maxm 100010#define eps 1e-4using namespace std;int vi[220],head[220],e,n,m,id[220],lab,num,dfn[220],low[220],Stack[220],top;double Max;struct Point{ double x,y;}p[210];struct Edge{ int u,v,next;}edge[Maxm];void init(){ memset(vi,0,sizeof(...
阅读全文
摘要:思路:直接引用论文的话。暂时先不考虑“使剩下的物品都放不下”的条件,那就是求 0-1 背包的所有可行方案。 用 Fi[j]表示前 i 件物品中选若干件总体积为 j 的方案数,初始为 F0[0]=1,转移方程是: Fi[j] = Fi-1[j] (Vi>j) Fi[j] = Fi-1[j] + Fi-1[j-Vi](j>=Vi) 显然这个算法的效率是 O(n*C)的,它计算了所有装放背包的方案数。 现在考虑“使剩下的物品都放不进去”的条件,如果剩下的物品中体积最小为 v,那么方案数就是 sum{ Fn[j] }(C>=j>C-v)。前提是我们事先确定了剩下中体积最小的是哪
阅读全文
摘要:思路:把价值看做体积,而价值的大小还是其本身,那么只需判断1-m中的每个状态最大是否为自己,是就+1;#include#include#include#include#define Maxn 100010#define Max(a,b) (a)>(b)?(a):(b)using namespace std;int dp[Maxn],num[110],v[110];struct Que{ int pos,val;}que[Maxn*2];int main(){ int n,m,i,j; while(scanf("%d%d",&n,&m)!=EOF,n&a
阅读全文
摘要:思路:这个方法要看《浅谈几类背包问题》这篇论文。#include"stdio.h"#define Max(a,b) (a)>(b)?(a):(b)int f[31],k[8];int main(){ int i,j,m,Case=0; while(scanf("%d%d%d%d%d%d",&k[1],&k[2],&k[3],&k[4],&k[5],&k[6])!=EOF,k[1]|k[2]|k[3]|k[4]|k[5]|k[6]) { for(i=0;i0) { if(k[i]=m*i;j--) ..
阅读全文
摘要:思路:裸的单调队列。#include#include#include#include#define Maxn 1000010using namespace std;int n,k,que[Maxn],num[Maxn],head,rear;int main(){ int i,j,a; while(scanf("%d%d",&n,&k)!=EOF) { head=1; rear=0; for(i=1;i=head&&num[que[rear]]>=num[i]) rear--; que...
阅读全文
摘要:#include#include#include#include#define Maxn 100010using namespace std;__int64 ans=0;int Stack[Maxn],top;int main(){ int n,i,j,a; while(scanf("%d",&n)!=EOF) { ans=0; top=0; for(i=1;i0&&Stack[top]<=a) top--; ans+=(__int64)top; Stack[+...
阅读全文
摘要:思路:将查询区间按右节点的升序排列,然后插入第i个数的时候,若nun[i]+1已经插入,那么就update(pre[num[i]+1],-1);pre[]表示的是该数的位置。同样若num[i]-1存在就update(pre[num[i]-1],-1);因为他么与num[i]属于一组,故只需一个存在就行。当查询的右边界r等于i时,只需对其左边界求和就行,Sum(qt[j].l)。#include#include#include#include#define Maxn 100010#define lowbit(x) (x&(-x))using namespace std;int C[Max
阅读全文
摘要:思路:dp[i][j]表示区间(i,j)中回文串的个数,那么dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1];如果str[i]==str[j],那么dp[i][j]+=dp[i+1][j-1]+1;#include#include#include#include#define Maxn 1010#define Mod 10007using namespace std;int dp[Maxn][Maxn];int main(){ int t,i,j,n,Case=0; char str[Maxn]; scanf("%d",&t);
阅读全文
摘要:思路:想用Tarjan算法进行缩点,并记录每个连通分支的点数。缩点完毕过后,找出所有出度或入度为0的连通分量,假设该连通分量的点数为num[i],那么ans=Max(ans,(n-num-1)*(n-num)+(num-1)*num+(n-num)*num-m);#include#include#include#include#define Maxn 100010#define Max(a,b) (a)>(b)?(a):(b)using namespace std;int head[Maxn],vi[Maxn],dfn[Maxn],low[Maxn],e,lab,top,Stack[Ma
阅读全文
摘要:思路:不管是Alice,还是Bob,每次操作都会影响最右下角的数,那么如果是1,Alice赢,否则Bob赢#include#include#include#include#define Maxn 100010#define lowbit(x) (x&(-x))using namespace std;int main(){ int n,m,i,j,t,a; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++) for(j=1;j<=
阅读全文
摘要:思路:找出所有 a#include#include#include#define Maxn 100010#define lowbit(x) (x&(-x))using namespace std;int C[Maxn],n;int Sum(int pos){ int sum=0; while(pos) { sum+=C[pos]; pos-=lowbit(pos); } return sum;}void update(int pos){ while(pos<=n) { C[pos]++; pos+...
阅读全文
摘要:思路:定义一个map容器用来记录数ai上次出现的位置。将查询区间按右边界升序进行排序,当插入第i个数ai时,pre[ai]+1---->i的区间就会多一个不同的数,其值就是ai,那么可以用update(pre[ai]+1,ai)来保存,但又不能影响i之后的位置,故用update(i,-ai)来消除。每次对于右边界时i的查询区间,只要对其左边界求和就行了,即Sum(qt[i].l)。#include#include#include#include#include#define Maxn 40010#define lowbit(x) (x&(-x))using namespace s
阅读全文
摘要:思路:这题的思路很容易想到,把所有时间点离散化,然后按时间一步一步来,当到达时间i的时候处理所有在i处的查询。这个代码怎一个挫字了得#include#include#include#include#include#define Maxn 100010#define lowbit(x) (x&(-x))using namespace std;int C[Maxn*3],n,ans[Maxn];struct Flower{ int l,r;}flower[Maxn];struct Lisan{ int val,type,l; int pos; int operator q...
阅读全文
摘要:思路:就是一个很普通的二维树状数组,注意的是x1,y1不一定在x2,y2的左下方。#include#include#include#include#define Maxn 1105#define lowbit(x) (x&(-x))using namespace std;int C[Maxn][Maxn],n=1010,LIST[Maxn][Maxn];int Sum(int i,int j){ int sum=0; int y; y=j; while(i) { j=y; while(j) { sum...
阅读全文

浙公网安备 33010602011771号