1. 程式人生 > >【DP】計劃11.8——(樹形依賴揹包總結)&&分數規劃思想

【DP】計劃11.8——(樹形依賴揹包總結)&&分數規劃思想

樹形依賴揹包指的就是一類具有樹形依賴關係的揹包問題。當選一個物品的前提是選另一件物品,而這些依賴關係構成了一個樹形關係。在容量有限的情況下,然後求最大的價值,這類問題我們就稱之為樹形依賴揹包。
樹形依賴揹包問題實際上是一類分組揹包問題,我們可以將每個點的子樹看成一個組,因為子樹內會選擇一定的點,但是選擇的點數只有一種情況,所以我們可以將子樹選擇iii[0,sizsonx]i∈[0,siz_{sonx}])的情況看成一類物品,然後就做分組揹包即可。
我們設f[i][j]f[i][j]表示點ii,字數裡選了jj容量的最大價值,那麼則有DP方程:
for(int i=k;i>=w[x];i--)
    for(int j=0;j<=k;j++){
         if(i+j>k) break;
         f[x][i+j]=max(f[x][i+j],f[x][i]+f[son][j])
}
一般的依賴關係會要求選擇當前子樹的樹根,因此初始狀態是f[x][w[x]]=v[x],並且在第一維列舉容量時只列舉到w[x]
還有一類DP方程,f[i][j]f[i][j]表示點ii字數內選擇了jj個點所獲得的最大的收益,那麼方程式也稍微變一下即可:
for(int i=siz[x];i>=1;i--)
    for(int j=0;j<=siz[son];j++){
         if(i+j>k) break;
         f[x][i+j]=max(f[x][i+j],f[x][i]+f[son][j])
}
這類方程有一個很實用的優化,就是我們剛開始初始化siz[x]=1
,然後每次列舉完一個兒子的時候,就執行語句siz[x]+=siz[son]。這樣可以大大降低複雜度,有巨佬指出,原來不進行優化的時間複雜度為O(n3)O(n^3),但是進行了這個sizsiz陣列的優化後,可以接近於O(n2)O(n^2)這也就是為什麼許多nn25002500的題目,也可以用樹形依賴揹包來做。
例題:
洛谷:P2014選課

題目描述

在大學裡每個學生,為了達到一定的學分,必須從很多課程裡選擇一些課程來學習,在課程裡有些課程必須在某些課程之前學習,如高等數學總是在其它課程之前學習。現在有N門功課,每門課有個學分,每門課有一門或沒有直接先修課(若課程a是課程b的先修課即只有學完了課程a,才能學習課程b)。一個學生要從這些課程裡選擇M門課程學習,問他能獲得的最大學分是多少?
輸入輸出格式
輸入格式:

第一行有兩個整數N,M用空格隔開。(1<=N<=300,1<=M<=300)

接下來的N行,第I+1行包含兩個整數ki和si, ki表示第I門課的直接先修課,si表示第I門課的學分。若ki=0表示沒有直接先修課(1<=ki<=N, 1<=si<=20)。

輸出格式:

只有一行,選M門課程的最大得分。

輸入輸出樣例
輸入樣例#1:

7 4
2 2
0 1
0 4
2 1
7 1
7 6
2 2

輸出樣例#1:

13

這道題就是最基本的樹形依賴揹包模板,就是上面說的第二類DP方程,甚至由於N的範圍很小,直接O(n3)O(n^3)的DP也不會超時
程式碼中的方程式與上文所述的方程式效果相同,但是一般會選用上文的那種,因為那種方程式配合sizsiz優化的時候複雜度更優
#include<bits/stdc++.h>
#define MAXN 205
using namespace std;
int read(){
	char c;int x;while(c=getchar(),c<'0'||c>'9');x=c-'0';
	while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';return x;
}
int n,m,cnt,siz[MAXN],head[MAXN],nxt[MAXN],f[MAXN][105];
struct node{
	int to,val;
}L[MAXN];
void add(int x,int y,int c){
	L[cnt]=(node){y,c};
	nxt[cnt]=head[x];head[x]=cnt;cnt++;
}
void get(int x){
	siz[x]=1;
	for(int i=head[x];i!=-1;i=nxt[i]){
		int to=L[i].to;
		get(to);siz[x]+=siz[to];
	}
}
int dfs(int x){
	for(int i=head[x];i!=-1;i=nxt[i]){
		int to=L[i].to;dfs(to);
		for(int j=siz[x]-1;j>=0;j--)
		 for(int k=0;k<=siz[to]-1;k++)
		  if(j>k) f[x][j]=max(f[x][j],f[x][j-k-1]+L[i].val+f[to][k]);
	}
}
int main()
{
	n=read();m=read();
	memset(head,-1,sizeof(head));
	memset(f,~0x3f,sizeof(f));
	for(int i=1;i<=n;i++){
		int x=read()+1,c=read();
		add(x,i+1,c);
	}
	for(int i=1;i<=n+1;i++) f[i][0]=0;
	get(1);dfs(1);
	printf("%d",f[1][m]);
	return 0;
}
洛谷:P1273有線電視網
題目要求不虧本的情況下最多的使用人數,我們採用第二種DP方式。最後checkcheck的時候只要ii從大到小列舉f[1][i]f[1][i],如果當前的f[1][i]f[1][i]大於等於0,那麼ii就是最多的使用人數。
#include<bits/stdc++.h>
#define MAXN 3005
using namespace std;
int read(){
    char c;int x;while(c=getchar(),c<'0'||c>'9');x=c-'0';
    while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';return x;
}
int n,m,cnt,ans,head[MAXN],nxt[MAXN],go[MAXN],dp[MAXN][MAXN],w[MAXN],son[MAXN],siz[MAXN];
struct node{
    int to,val;
}L[MAXN];
void add(int x,int y,int c){
    L[cnt]=(node){y,c};
    nxt[cnt]=head[x];head[x]=cnt;cnt++;
}
int dfs(int x){    //這個操作很silly,大家千萬不要學,又慢又長。直接在轉移時更新既短又快
    siz[x]=1;
    for(int i=head[x];i!=-1;i=nxt[i]){
        int to=L[i].to;
        siz[x]+=dfs(to);
    }
    return siz[x];
}
void calc(int x){
    if(x>n-m){dp[x][1]=w[x];return;}
    for(int i=head[x];i!=-1;i=nxt[i]){
        int to=L[i].to;calc(to);
        for(int j=siz[x];j>=0;j--)
          for(int k=1;k<=siz[to];k++)
           if(j>=k) dp[x][j]=max(dp[x][j],dp[x][j-k]+dp[to][k]-L[i].val);
    }
}
int main()
{
    n=read();m=read();
    memset(head,-1,sizeof(head));
    memset(dp,~0x3f,sizeof(dp));
    for(int i=1;i<=n;i++) dp[i][0]=0;
    for(int i=1;i<=n-m;i++){
        son[i]=read();
        for(int j=1;j<=son[i];j++){
            int x=read(),y=read();add(i,x,y);
        }
    }
    for(int i=1;i<=m;i++) w[n-m+i]=read();
    dfs(1);calc(1);
    for(int i=0;i<=n;i++) if(dp[1][i]>=0) ans=i;
    printf("%d",ans);
    return 0;
}
Codeforces:815C
這道題用的是第二種方程,不同的是依賴關係只適用於優惠,因此即使我們要開兩個陣列,ff陣列記錄的是滿足依賴的能夠享受優惠的情況,gg陣列是不滿足依賴的情況,gg的轉移其實類似於ff,只是外層列舉容量那一維要倒著一直列舉到00
#include<bits/stdc++.h>
#define MAXN 5005
#define ll long long
using namespace std;
ll read(){
	char c;ll x;while(c=getchar(),c<'0'||c>'9');x=c-'0';
	while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';return x;
}
ll n,m,ans,flag,v[MAXN],dc[MAXN],f[MAXN][MAXN],g[MAXN][MAXN];
ll cnt,head[MAXN<<1],nxt[MAXN<<1],go[MAXN<<1],siz[MAXN];
void add(ll x,ll y){
	go[cnt]=y;nxt[cnt]=head[x];head[x]=cnt;cnt++;
}
void dfs(ll x){
	register int i,j,k;
	g[x][0]=0;f[x][1]=v[x]-dc[x];g[x][1]=v[x];siz[x]=1;
	for(k=head[x];k!=-1;k=nxt[k]){
		ll to=go[k];dfs(to);
		for(i=siz[x];i>=0;i--)
		 for(j=1;j<=siz[to];j++)
		  g[x][i+j]=min(g[x][i+j],g[x][i]+g[to][j]);
		for(i=siz[x];i>=1;i--)
		 for(j=1;j<=siz[to];j++)
		  f[x][i+j]=min(f[x][i+j],f[x][i]+min(f[to][j],g[to][j])); 
		siz[x]+=siz[to];
	}
}
int main()
{
	n=read();m=read();register int i;
	memset(head,-1,sizeof(head));
	memset(f,127,sizeof(f));
	memset(g,127,sizeof(g));
	for(i=1;i<=n;i++){
		v[i]=read();dc[i]=read();
		if(i>1){ll x=read();add(x,i);}
	}
	dfs(1);
	for(i=n;i;i--)
	 if(f[1][i]<=m||g[1][i]<=m){flag=1;printf("%d",i);break;}
	if(!flag) puts("0");
	return 0;
}
BZOJ:2427軟體安裝

Description

現在我們的手頭有N個軟體,對於一個軟體i,它要佔用Wi的磁碟空間,它的價值為Vi。我們希望從中選擇一些軟體安裝到一臺磁碟容量為M計算機上,使得這些軟體的價值儘可能大(即Vi的和最大)。

但是現在有個問題:軟體之間存在依賴關係,即軟體i只有在安裝了軟體j(包括軟體j的直接或間接依賴)的情況下才能正確工作(軟體i依賴軟體j)。幸運的是,一個軟體最多依賴另外一個軟體。如果一個軟體不能正常工作,那麼它能夠發揮的作用為0。

我們現在知道了軟體之間的依賴關係:軟體i依賴軟體Di。現在請你設計出一種方案,安裝價值儘量大的軟體。一個軟體只能被安裝一次,如果一個軟體沒有依賴則Di=0,這時只要這個軟體安裝了,它就能正常工作。

Input

第1行:N, M (0<=N<=100, 0<=M<=500)
第2行:W1, W2, … Wi, …, Wn (0<=Wi<=M )
第3行:V1, V2, …, Vi, …, Vn (0<=Vi<=1000 )
第4行:D1, D2, …, Di, …, Dn (0<=Di<=N, Di≠i )

Output

一個整數,代表最大價值。

Sample Input
3 10

5 5 6

2 3 4

0 1 1
Sample Output
5

這道題噁心的地方就在於整張圖可能是一個環,也可能是一個森林。
因此我們要先用TarjanTarjan縮點,將所有的環縮成一個點,這個點的v=vxw=wxv=\sum v_x \ \ \ w=\sum w_x,x是這個環中的點。這個也很好證明,因為形成了一個環形依賴,所以環中每個點都得同時選才行。
由於縮完點可能是森林,所以我們建一個虛點00,並且v[0]=w[0]=0v[0]=w[0]=0,然後從00開始轉移即可。
這道題運用的是上文的第一種DP方式,所以不存在sizsiz優化,複雜度是跑不到上界的O(n3)O(n^3)
#include<bits/stdc++.h>
#define MAXN 505
using namespace std;
int read(){
    char c;int x=0,y=1;while(c=getchar(),(c<'0'||c>'9')&&c!='-');
    if(c=='-') y=-1;else x=c-'0';while(c=getchar(),c>='0'&&c<='9')
    x=x*10+c-'0';return x*y;
}
int n,m,cnt,top,ans,w[MAXN],v[MAXN],head[MAXN<<1],nxt[MAXN<<1],go[MAXN<<1],in[MAXN];
int ta,co,dfn[MAXN],low[MAXN],vis[MAXN],sta[MAXN],col[MAXN],fa[MAXN],f[MAXN][505];
vector<int> g[MAXN];
struct node{
    int w,v;
}F[MAXN];
void add(int x,int y){
    go[cnt]=y;nxt[cnt]=head[x];head[x]=cnt;cnt++;
}
void tarjan(int x){
    dfn[x]=low[x]=++ta;
    vis[x]=1;sta[++top]=x;
    for(int i=head[x];i!=-1;i=nxt[i]){
        int to=go[i];
        if(!dfn[to]) tarjan(to),low[x]=min(low[x],low[to]);
        else if(vis[to]) low[x]=min(low[x],dfn[to]);
    }
    if(dfn[x]==low[x]){
        co++;int now=0;
        while(now!=x){
            now=sta[top--];
            vis[now]=0;col[now]=co;
            F[co].w+=w[now];
            F[co].v+=v[now];
        }
    }
}
int find(int x){
    if(fa[x]!=x) fa[x]=find(fa[x]);
    return fa[x];
}
void unionn(int x,int y){
    x=find(x);y=find(y);
    fa[y]=x;
}
void dfs(int x){
    if(F[x].w>m) return;
    f[x][F[x].w]=F[x].v;
    for(int i=0;i<g[x].size();i++){
        int to=g[x][i];
        dfs(to);
        for(int j=m;j>=F[x].w;j--)
         for(int k=0;k<=m;k++){
            if(j+k>m) break;
            f[x][j+k]=max(f[x][j+k],f[x][j]+f[to][k]);
         }
    }
}
int main()
{
    n=read();m=read();
    memset(head,-1,sizeof(head));
    for(int i=1;i<=n;i++) w[i]=read();
    for(int i=1;i<=n;i++) v[i]=read();
    for(int i=1;i<=n;i++){
        int x=read();
        if (x)add(x,i);
    }
    for(int i=1;i<=n;i++)
      if(!dfn[i]) tarjan(i);
    for(int i=1;i<=co;i++) fa[i]=i;
    for(int x=1;x<=n;x++)
     for(int i=head[x];i!=-1;i=nxt[i]){
        int to=go[i];
        if(find(col[x])!=find(col[to])){
            unionn(col[x],col[to]);in[col[to]]++;
            g[col[x]].push_back(col[to]);
         }
     }
    for(int i=1;i<=co;i++)
     if(!in[i]) g[0].push_back(i);
    F[0]=(node){0,0};
    dfs(0);
    for(int i=0;i<=m;i++) ans=max(ans,f[0][i]);
    printf("%d",ans);
    return 0;
}

BZOJ:4753最佳團體

Description
JSOI資訊學代表隊一共有N名候選人,這些候選人從1到N編號。方便起見,JYY的編號是0號。每個候選人都由一位
編號比他小的候選人Ri推薦。如果Ri=0則說明這個候選人是JYY自己看上的。為了保證團隊的和諧,JYY需要保證,
如果招募了候選人i,那麼候選人Ri"也一定需要在團隊中。當然了,JYY自己總是在團隊裡的。每一個候選人都有
一個戰鬥值Pi",也有一個招募費用Si"。JYY希望招募K個候選人(JYY自己不算),組成一個性價比最高的團隊。
也就是,這K個被JYY選擇的候選人的總戰鬥值與總招募總費用的比值最大。

Input
輸入一行包含兩個正整數K和N。
接下來N行,其中第i行包含3個整數Si,Pi,Ri表示候選人i的招募費用,戰鬥值和推薦人編號。
對於100%的資料滿足1≤K≤N≤2500,0<"Si,Pi"≤10^4,0≤Ri<i

Output
輸出一行一個實數,表示最佳比值。答案保留三位小數。

Sample Input
1 2

1000 1 0

1 1000 1
Sample Output
0.001

這道題需要結合分數規劃的知識,分數規劃指的是一類求aibi\frac{\sum a_i}{\sum b_i}最大值得問題,我們設aibi&gt;x\frac{\sum a_i}{\sum b_i}&gt;x,那麼ai&gt;xbi\sum a_i&gt;x*\sum b_i,移項得aixbi&gt;0\sum a_i-x*\sum b_i&gt;0,所以我們可以去二分列舉xx,然後依據這個大於00的等式進行checkcheck
對於這道題,我們去二分列舉最優值,將每個點的價值賦值為a[i]-x*b[i],然後進行樹形依賴揹包,求出選中kk個人之後的最大價值,如果最大價值大於00,那麼也就是checkcheck滿足條件。
#include<bits/stdc++.h>
#define MAXN 2550
#define db double
#define eps 1e-6
using namespace std;
int read(){
    char c;int x;while(c=getchar(),c<'0'||c>'9');x=c-'0';
    while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';return x;
}
int n,k,cnt,a[MAXN],b[MAXN],siz[MAXN];
int head[MAXN<<1],nxt[MAXN<<1],go[MAXN<<1];
db l,r,mid,ans,v[MAXN],f[MAXN][MAXN];
void add(int x,int y){
    go[cnt]=y;nxt[cnt]=head[x];head[x]=cnt;cnt++;
}
void dfs(int x){
    f[x][1]=v[x];siz[x]=1;
    for(int i=2;i<=k;i++) f[x][i]=-2147483647;
    for(int i=head[x];i!=-1;i=nxt[i]){
        int to=go[i];dfs(to);
        for(int j=siz[x];j>=1;j--)
         for(int p=0;p<=siz[to];p++){
            if(j+p>k) break;
            f[x][j+p]=max(f[x][j+p],f[x][j]+f[to][p]);
         }
        siz[x]+=siz[to];
    }
}
int main()
{
    k=read();n=read();k++;
    memset(head,-1,sizeof(head));
    for(int i=1;i<=n;i++){
        b[i]=read();a[i]=read();
        int x=read();add(x,i);
    }
    l=0;r=1000000;
    while(l<=r){
        mid=(l+r)/2;
        for(int i=1;i<=n;i++) v[i]=1.0*a[i]-mid*b[i]; 
        dfs(0);
        if(f[0][k]>=0) ans=mid,l=mid+eps;
        else r=mid-eps;
    }
    printf("%.3f",ans);
    return 0;
}
BZOJ:4033樹上染色

Description
有一棵點數為N的樹,樹邊有邊權。給你一個在0~N之內的正整數K,你要在這棵樹中選擇K個點,將其染成黑色,並將其他的N-K個點染成白色。將所有點染色後,你會獲得黑點兩兩之間的距離加上白點兩兩之間距離的和的收益。
問收益最大值是多少。
Input
第一行兩個整數N,K。
接下來N-1行每行三個正整數fr,to,dis,表示該樹中存在一條長度為dis的邊(fr,to)。
輸入保證所有點之間是聯通的。
N<=2000,0<=K<=N
Output
輸出一個正整數,表示收益的最大值。
Sample Input
5 2

1 2 3

1 5 1

2 3 1

2 4 2

Sample Output
17

【樣例解釋】

將點1,2染黑就能獲得最大收益。

這道題也算在樹形揹包的範疇裡,但是沒有依賴關係。我們設f[i][j]f[i][j]表示點ii,子樹裡染了了jj個黑點所能產生的貢獻。
這個定義的關鍵在於貢獻,因為子樹裡染了jj個黑點,產生的貢獻是與子樹外的點無關的(因為我們只靠慮當前的貢獻,後面的貢獻會在之後的計算中被統計)
我們思考如何統計這個貢獻,假設當前點為xx,它的一個兒子為sonson,並且sonson的子樹裡染了jj個黑點,那麼這jj個黑點在當前的貢獻就是f[son][j]+L[i].valk(mk)+L[i].val(siz[son]k)(nm(siz[son]k))f[son][j]+L[i].val*k*(m-k)+L[i].val*(siz[son]-k)*(n-m-(siz[son]-k))
這個式子怎麼理解呢?f[son][j]f[son][j]就是兒子子樹中到兒子節點產生的貢獻,那麼加上從xxsonson的這條邊所(L[i].valL[i].val)產生的貢獻,也就是到xx為止的貢獻。
如果子樹內有kk個黑點,那麼這kk個點總共會與外面的黑點形成k(mk)k*(m-k)個點對,每個點對都經過這條邊,所以是L[i].valk(mk)L[i].val*k*(m-k)。那麼同理,白色的點會形成(siz[son]k)(nm(siz[son]k))(siz[son]-k)*(n-m-(siz[son]-k))個點對,也就產生了L[i].val(siz[son]k)(nm(siz[son]k))L[i].val*(siz[son]-k)*(n-m-(siz[son]-k))的貢獻。
明白怎麼統計貢獻之後,就是簡單的樹形揹包了。依舊要使用sizsiz優化,否則複雜度過不去。
#include<bits/stdc++.h>
#define MAXN 2005
#define ll long long
using namespace std;
int read(){
    char c;int x;while(c=getchar(),c<'0'||c>'9');x=c-'0';
    while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';return x;
}
int n,m,cnt,head[MAXN<<1],nxt[MAXN<<1];
int siz[MAXN],fa[MAXN];
ll f[MAXN][MAXN];
struct node{
    int to,val;
}L[MAXN<<1];
void add(int x,int y,int c){
    L[cnt]=(node){y,c};
    nxt[cnt]=head[x];head[x]=cnt;cnt++;
    L[cnt]=(node){x,c};
    nxt[cnt]=head[y];head[y]=cnt;cnt++;
}
void dp(int x,int fa){
    siz[x]=1;
    for(int i=head[x];i!=-1;i=nxt[i]){
        int to=L[i].to;
        if(to==fa) continue;dp(to,x);
        for(int j=min(siz[x],m);j>=0;j--)
         for(int k=min(siz[to],m);k>=0;k--){
            f[x][j+k]=max(f[x][j+k],f[x][j]+f[to][k]+L[i].val*1ll*k*(m-k)+L[i].val*1ll*(siz[to]-k)*(n-m-(siz[to]-k)));
         }
        siz[x]+=siz[to];
    }
}
int main()
{
    n=read();m=read();
    memset(head,-1,sizeof(head));
    memset(f,-0x3f,sizeof(f));
    for(int i=1;i<=n;i++) f[i][0]=f[i][1]=0;
    for(int i=1;i<n;i++){
        int x=read(),y=read(),c=read();
        add(x,y,c);
    }
    dp(1,0);
    printf("%lld",f[1][m]);
    return 0;
}

相關推薦

DP計劃11.8——樹形依賴揹包總結&&分數規劃思想

樹形依賴揹包指的就是一類具有樹形依賴關係的揹包問題。當選一個物品的前提是選另一件物品,而這些依賴關係構成了一個樹形關係。在容量有限的情況下,然後求最大的價值,這類問題我們就稱之為樹形依賴揹包。 樹形依賴揹包問題實際上是一類分組揹包問題,我們可以將每個點的子樹看成

2018.11.08CodeForces990F. Flow Control樹形DP

傳送門 解析: 首先無解的情況當且僅當權值和不為0。 不然由於圖是聯通的,一定存在解,而實際上我們並不需要圖的性質,我們只需要樹的性質就可以做樹形DP了。 我們直接計算它子樹內部會有多少權值需要轉移,然後沿這條邊轉移就行了。 程式碼: #include&l

HDU1520 Anniversary party樹形dp

pre ret set rsa main eof hdu opened event 題目 題目 分析 帶權值的樹上最大獨立集 代碼 1 #include <bits/stdc++.h> 2 using nam

2018.12.08BZOJ2152聰聰可可樹形DP

傳送門 解析: 維護從子樹內到該節點上有多少條路徑模3餘0,1,2就行了。 統計考慮以每個點為 l c

ARC101ERibbons on Tree樹形DP,容斥原理

Description 給定一棵點數為偶數的樹,要求有多少種將點兩兩配對的方案使得每一條邊至少被一對匹配點之間的最短路徑覆蓋。 Solution 根本想不到的DP系列。 首先考慮一個容斥

DP疊放箱子問題兩種方法

題目描述 某港口有一批集裝箱,將其編號,分別為1至N。每一個箱子的外型尺寸都是一樣的,現在要將其中某些集裝箱疊放起來,集裝箱疊放的規則如下:   1)每個集裝箱上最多隻能直接疊放一個集裝箱。   2)編號較小的集裝箱不能放在編號較大的集裝箱之上。   3)每個集裝箱都給出了自身的重量和可

Luogu3398倉鼠找sugar樹鏈剖分

name -m pac tor int modify 可能 iostream algorithm 【Luogu3398】倉鼠找sugar(樹鏈剖分) 題面 題目描述 小倉鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每個節點的編號為1~n。地下洞穴是一個樹形結構

UVA536 Tree Recovery樹型結構基礎

cnblogs using include http tree c++ code div str 題目 題目 ? ? 分析 莫名A了 ? ? 代碼 #include <bits/stdc++.h> using namespace std; string s1

POJ2774Long Long Message後綴數組

火車票 字符串 cat ios swa char 們的 same getc 【POJ2774】Long Long Message(後綴數組) 題面 Vjudge Description Little cat在Byterland的首都讀物理專業。這些天他收到了一條悲傷地信息:

HDOJA Math Problem對pow()的理解

題意 hdu pan 打了 AC 輸入 show color 執行效率 A Math Problem http://acm.hdu.edu.cn/showproblem.php?pid=6182 題意:輸入一個n,問有多少個k的k次冪<=n(k=1,2,3...) 思

BZOJ2007: [Noi2010]海拔平面圖轉對偶圖

using targe line problem max 最小 mem AR pop 題目 傳送門:QWQ 分析 左上角是0,右下角是1。那麽大概整張圖是由0 1構成的。 那麽我們要找到0和1的分界線,值就是最小割。 然後變成求原圖最小割。 考慮

P1330封鎖陽光大學圖論、BFS

/* P1330 封鎖陽光大學 圖論 2018/11/22 */ #include<bits/stdc++.h> using namespace std; const int maxn=10010; vector<int>point[maxn];//STL

模板樹套樹線段樹套Splay

如題,這是一個模板。。。 #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <cctype> #defi

Codeforces1073CVasya and Robot二分+思維+字首和

題目連結 C. Vasya and Robot time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output

Java圖形介面實踐不斷更新中!

建立一個簡單的窗體 package practice; import javax.swing.JButton; import javax.swing.JFrame; public class Test { public static void main(String[] args) {

leetcode兩數之和C、Python解答

題目: 給定一個整數陣列和一個目標值,找出陣列中和為目標值的兩個數。 你可以假設每個輸入只對應一種答案,且同樣的元素不能被重複利用。 示例: 給定 nums = [2, 7, 11, 15], target = 9 因為 nums[0] + nums[1] =

HDU1022Train Problem I出棧可行問題

題目大意:給出一個數(車的數目),兩個字串(前一個為現有車的排序,第二個為要組成的車的排序), Sample Input 3 123 321 3 123 312 Sample Output Yes. in in in out out out FINI

MATLAB prod 函式介紹Product of array elements

prod Product of array elements Syntax B = prod(A) B = prod(A,dim) B = prod(___,type) B = prod(___,nanflag) Description B = prod(A)

數論The Super Powers 英語+log函式使用

題目連結: We all know the Super Powers of this world and how they manage to get advantages in political warfare or even in other sectors. B

BZOJ1015JSOI2008星球大戰Starwar離線並差集

傳送門 一道簡單題 所謂正難則反 我們考慮離線從後往前操作 就變成了每次加一個點求當前聯通塊個數 並查集就完了唄 程式碼稍微寫的有些繁瑣 但肯定還是可以看的 #include<bits/stdc++.h> using namespace std;