記録上2019夏

7.13 1日目wfj妖精データ構造先輩
 7.14 2日目DP
 グラフ理論の7.16 3日目のhankpipi(YZH)
 7.17 Day4数学


バーストゼロljq先輩関連する7.22 1日目の文字列
  T1中央値(中央値)  
  イタリアということ:長さを考えると\(N- \)の配置、すべて満たしてください\(1≤i≤j≤nを\)\ (\ 2 J-i≡0\ MOD ) の数\((I、J)\)第一の配置によって算出さ、\(Iは\)を介して\(J \)の中央値を構成する要素のセット\(M [I:J] \) および取得\(M [I:J] * i *がj個\) とを。\(n個の\当量10 ^ {
4} \)   溶液:問題解決を二重にリンクされたリストシニア(学んだことはありません)

#include <iostream>
#include <vector>
#include<cstdio>
using namespace std;
typedef long long int64;
int main() {
    freopen("median.in","r",stdin);
    freopen("median.out","w",stdout);
    int n; cin >> n;
    vector<int> element(n);
    for (int i = 0; i < n; i += 1) {
        cin >> element[i];
    }
    vector<pair<int, int>> neighbours(n + 1);
    int64 result = 0;
    for (int i = 0; i < n; i += 1) {
         //如果索引在[i,n]范围内,则该值有效 
        vector<bool> valid(n + 1, false);
        for (int j = i; j < n; j += 1) {
            valid[element[j]] = true;
        }
        valid[n + 1] = true;
        int last = 0;
        //值的数目>中间值,较低值的数目<=中间值
        //mid->中间值
        int bigger = (n - i), lower = 0, mid = 0;    
        //  计算每个值,左边和右边的下一个有效值 
        for (int j = 1; j <= n; j += 1) {
            if (not valid[j]) {
                continue;
            }
            if (bigger > lower) {
                mid = j;
                bigger -= 1;
                lower += 1;
            }
            // 最后一个元素将是当前元素左边的元素
            // 最后一个元素右边的元素将是这个元素
            neighbours[j].first = last;
            neighbours[last].second = j;
            last = j;
        }
        for (int j = n -1 ; j >= i; j -= 1) {
            if (lower == bigger + 1) {
                // this can be any formula, whatsoever
                result += (int64) (j + 1) * (i + 1) * mid;
            } 
            // 值位于擦除值的左侧和右侧
            int left = neighbours[element[j]].first;
            int right = neighbours[element[j]].second;
            // 从“列表”中删除此列表
            neighbours[left].second = right;
            neighbours[right].first = left;
            // 更新中间值、较大或较小的值。
            if (element[j] == mid) {
                bigger -= 1;
                mid = right;
            } else if (element[j] < mid) {
                lower -= 1;
            } else {
                bigger -= 1;
            }
            // even thou it requires only 1 iteration, the implementation
            // seems cleaner this way to put the median on the right spot
            // move the median to the left
            while (lower > bigger) {
                mid = neighbours[mid].first;
                bigger += 1;
                lower -= 1;
            }

            // move the median to the right
            while (bigger > lower) {
                mid = neighbours[mid].second;
                bigger -= 1;
                lower += 1;
            }
        }
    }

    cout << result << '\n';
    return 0;
}

そして、書かれた自分を出しYY標準のintはしかし、診察室にバーストよりも離れて高速に実行
複雑\(O(N ^ {2 })\)

#include<bits/stdc++.h>
using namespace std;
#define maxn 10005
int n;
int a[maxn],cnt[maxn];
long long ans;
inline void solve()
{
    int l=1,r=0,cntt=0,tmp;
    long long mid=0;
    for(int tl=1;tl<=n;++tl) 
    {
        for(int tr=tl;tr<=n;tr+=2)
        {
            while(l<tl)
            {
                if(a[l]<=mid) --cntt;//左端点显然只会递增
                --cnt[a[l++]];
            }
            while(r<tr)
            {
                if(a[++r]<=mid) ++cntt;
                ++cnt[a[r]];
            }
            while(r>tr)
            {
                if(a[r]<=mid) --cntt;
                --cnt[a[r--]];
            }
            tmp=((tr-tl)>>1)+1;
            if(tmp==1)
            {
                mid=a[tl];
                cntt=1;
                ans+=mid*tl*tr;
                continue;
            }
            while(cntt<tmp)
                cntt+=cnt[++mid];
            while(cntt>dizengtmp)
            {
                if(cntt-cnt[mid]<tmp) break;
                cntt-=cnt[mid--];
            }
            while(cntt==tmp)
            {
                if(cnt[mid]!=0) break;//处理mid为零的情况
                --mid;
            }
            ans+=mid*tl*tr;
        }
    }
}
int main()
{
    freopen("median.in","r",stdin);
    freopen("median.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
        scanf("%d",&a[i]);
    solve();
    printf("%lld",ans);
    return 0;
}

T2セット(セット)
  問題の意味:ある\(\ N-)ツリーのノードは、ルート番号\(1 \)は、最初に各ノードの空集合があります。次に形式である操作の数を実行する:このノードにルートとするサブツリー内のすべてのノードのために、その対応するセットの増加または要素を削除\(X \) 操作の各ノードは、その祖先ノードのすべてが完了したすべての操作の後に行われなければなりません。すでにの要素が含まれ\(のx \)強化要素の実装のコレクションです\(X \)の操作を、またはの要素が含まれていません(X \)\コレクションが要素を削除する(X \)\ではありませんインパクトのコレクション。
  最後に、コレクションのサイズに対応する各ノードをお願いします。
  入力フォーマット:最初のライン入力は正の整数含む\(N-を\) \(N-1 \)の各列に2つの正の整数行\(U \)を、\ (V \)は、接続されたツリーの存在を示している\(U、V \)側の2点を。その後\(N- \)行、第\(Iは\)最初の整数の行\(K_ {I} \) 続いて\(K_ {I} \)整数\(X_ {J} \)表し(Iは\)\の操作に対応するノード。場合\(X_ {J}は\)陽性である、それは要素を追加することを示している(\ X_ {J})\場合、\(X {J}は\)負であり、それは要素の意味\(X_ {J}を\) 確保\を(N- \のLeq ^ {10}。5、\ FORALL X_ {I} ,. 1 \のLeq X_ {I} \ n型のLeq \) 同じノードは、いずれかの要素の2倍以上の動作ではありません。
  ソリューション:直接DFS、ノードのコレクションを維持するための方法、回顧の回復
  複雑\(O(N + nは\ nでログ)\)

#include<bits/stdc++.h>
using namespace std;
#define maxn 100005
struct Edge
{
    int fr,to;
}eg[maxn];
set<int> op[maxn],s;
set<int>::iterator it;
int edgenum,n,head[maxn],ans[maxn];
inline void add(int fr,int to)
{
    eg[++edgenum].fr=head[fr];
    eg[edgenum].to=to;
    head[fr]=edgenum;
}
inline void dfs(int now)
{
    int tmp;
    for(it=op[now].begin();it!=op[now].end();)
    {
        tmp=*it;
        ++it;
        if(tmp>0)
        {
            if(s.count(tmp)) op[now].erase(tmp);
            else s.insert(tmp);
        }
        else
        {
            if(!s.count(-tmp)) op[now].erase(tmp);
            else s.erase(-tmp);
        }
    }
    ans[now]=s.size();
    for(int i=head[now];i;i=eg[i].fr)
        dfs(eg[i].to);
    for(it=op[now].begin();it!=op[now].end();++it)
    {
        tmp=*it;
        if(tmp>0) s.erase(tmp);
        else s.insert(-tmp);
    }
}
int main()
{
    freopen("set.in","r",stdin);
    freopen("set.out","w",stdout);
    scanf("%d",&n);
    int u,v,k;
    for(int i=1;i<n;++i)
        scanf("%d%d",&u,&v),add(u,v);
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&k);
        for(int j=1;j<=k;++j)
            scanf("%d",&u),op[i].insert(u);
    }
    dfs(1);
    for(int i=1;i<=n;++i)
        printf("%d\n",ans[i]);
    return 0;
}

T3スタークラフト(クラフト)
  質問面:
  狭い高地戦場が考えられる\(式中、R * Cは\)グリッドアレイの、各ボックスが通って2例を介して利用不可能であってもよいです。
  いつもの正方形を通じ占める海洋とzergling。二zerglingは同じ広場にすることができますが、いずれかの時間の海洋でのいずれかではないzerglingは同じボックスで死亡していません。
  海洋生物とzergling値(HP)、海洋生物の初期値の両方持っている\(m個\) すべての値が初期生命zerglingさを\(Z \)
  ターンベースのゲームは各ラウンド、海洋最初のアクションでは、として抽象化することができます。海洋は、(非常に狭いため、ハイツ、海洋は高地のどこに打つことができzerglingターゲットを削減するセルの縦または横方向に移動するように選択することができ、または各銃zergling.marine現場に向かって立ってのみ撮影しzergling寿命の値\(1 \)生活の値をzerglingにまで低減される点、\(0 \)これは、ポイント以下のときに死んでしまいます。海洋事業の完了後、すべてがzerglingと隣接する海洋、海洋攻撃それは、そうでない場合は、現在の位置に沿って前方に1つのスペース最短海洋現在の位置になります場合にのみ、複数存在する場合にも、動作しますまだ死んでいないzergling記事の最短は、行動をしようとするためには、右の順に、左を押しますzergling(例えば、左の場合は、左に行きますzergling、最短あります)。パスが唯一の海洋にzerglingされていない場合は、それが動かないことに注意してください。の2つが同じセルの海洋に同時にzergling場合は、海洋生物の値だけ減らす\(1 \)ポイントを、それ以外の攻撃は、それぞれzergling原因になります海洋生物の価値の減少\(1 \)ポイント。
  ターン終了時に、あなたは海洋生物がの値に低下した場合はすべて、ゲームの勝利をzergling死亡したと考えている場合、\(\ 0)の点以下、またはゲーム\(T \)ラウンドまだ勝利が失敗ゲームとみなされていません。あなたは、勝利のために必要なラウンドの最小数の出力を得ることが可能ならばプレーヤーは、勝つかどうかを判断する必要があります。
入力フォーマット:最初の行r、C、T。次に、R Cの文字行それぞれ、「1」は非貫通表し、「M」は「Z」および「Z」は、2つzerglingの初期位置を表し、maringの初期位置を表しています。最後に、Bは、海洋とzergling馬力です。確保\(1 \のLeq M \のLeq 16 \)、\ (1 \のLeq Z \のLeq 99 \)、\を(1 \のLeq T \のLeq 50 \)、\ (1 \ R&LTのLeq、
  ソリューション:爆発見つかりました??? Dの高齢者が検索されていない
  複雑\(O(R&LT *さT * M。3 ^ {^} * {C}。3)\) 通過することができます。

#include<bits/stdc++.h>
using namespace std;
char mp[10][10];
int r,c,T,hp_m,hp_z,m,z1,z2;
int pos[40][40],wei[40][40],near[40][40];
int dx[4]={0,-1,0,1},dy[4]={-1,0,1,0};
int dp[55][40][40][40][18];
int go(int now,int d)//mergling的行动
{
    int i=(now-1)/c,j=(now-1)%c;
    int di=i+dx[d],dj=j+dy[d];
    if(di<0||dj<0||di>=r||dj>=c||mp[di][dj]=='1') return -1;
    return pos[di][dj];
}
int zgo(int now,int to)zergling的行动
{
    if(near[now][to]||!now) return now;
    int res=-1,dis=0x3f3f3f3f;
    for(int d=0;d<4;++d)
    {
        int tmp=go(now,d);
        if(tmp==-1) continue;
        if(wei[tmp][to]<dis) dis=wei[tmp][to],res=tmp;
    }
    if(dis>100) return now;
    return res;
}
inline void cmin(int& a,int b)
{
    a=a<b?a:b;
}
int main()
{
    freopen("craft.in","r",stdin);
    freopen("craft.out","w",stdout);
    scanf("%d%d%d",&r,&c,&T);
    for(int i=0;i<r;++i)
        scanf("%s",mp[i]);
    scanf("%d%d",&hp_m,&hp_z);
    m=z1=z2=-1;
    for(int i=0;i<r;++i)
        for(int j=0;j<c;++j)
        {
            pos[i][j]=i*c+j+1;
            if(mp[i][j]=='z'||mp[i][j]=='Z')
            {dierwei
                if(z1==-1) z1=pos[i][j];
                else z2=pos[i][j];
            }
            else if(mp[i][j]=='M') m=pos[i][j];
        }
    memset(wei,0x3f,sizeof(wei));
    for(int i=0;i<r;++i)//最短路
        for(int j=0;j<c;++j)
        {
            if(mp[i][j]=='1') continue;
            if(i&&mp[i-1][j]!='1') wei[pos[i][j]][pos[i-1][j]]=1;
            if(i!=r-1&&mp[i+1][j]!='1') wei[pos[i][j]][pos[i+1][j]]=1;
            if(j&&mp[i][j-1]!='1') wei[pos[i][j]][pos[i][j-1]]=1;T
            if(j!=c-1&&mp[i][j+1]!='1') wei[pos[i][j]][pos[i][j+1]]=1;
            wei[pos[i][j]][pos[i][j]]=0;
        }
    int size=r*c;
    for(int i=1;i<=size;++i)//判断两格相邻
        for(int d=0;d<4;++d)
            if(go(i,d)!=-1) near[i][go(i,d)]=1;
    for(int k=1;k<=size;++k)
        for(int i=1;i<=size;++i)
            for(int j=1;j<=size;++j)
                cmin(wei[i][j],wei[i][k]+wei[k][j]);
    memset(dp,0x3f,sizeof(dp));
    dp[0][m][z1][z2][hp_m]=dp[0][m][z2][z1][hp_m]=hp_z<<1;//第一维时间,第二维maring的行动,第三维一只zergling,第四位另一只,第五维是maring剩余的hp
    for(int t=0;t<T;++t)
        for(int tm=1;tm<=size;++tm)
            for(int tz1=0;tz1<=size;++tz1)
                for(int tz2=0;tz2<=size;++tz2)
                    for(int thp=1;thp<=hp_m;++thp)
                    {
                        int hp_now=dp[t][tm][tz1][tz2][thp];
                        if(hp_now>100) continue;
                        for(int d=0;d<4;++d)
                        {
                            int nm=go(tm,d);
                            if(nm==-1||nm==tz1||nm==tz2) continue;
                            int v=0;
                            int nz1=zgo(tz1,nm),nz2=zgo(tz2,nm);
                            if(near[tz1][nm]) ++v;
                            if(near[tz2][nm]&&tz1!=tz2&&hp_now>hp_z) ++v;
                            if(thp>v) cmin(dp[t+1][nm][nz1][nz2][thp-v],hp_now);
                        }
                        int nz1=zgo(tz1,tm),nz2=zgo(tz2,tm);
                        if(hp_now==1)
                        {
                            printf("WIN\n%d\n",t+1);
                            return 0;
                        }
                        int v=0;
                        if(near[tz1][tm]) ++v;
                        if(near[tz2][tm]&&tz1!=tz2&&hp_now-1>hp_z) ++v;
                        if(thp>v)
                        {
                            if(hp_now-1>hp_z) cmin(dp[t+1][tm][nz1][nz2][thp-v],hp_now-1);
                            else cmin(dp[t+1][tm][nz1][0][thp-v],hp_now-1);
                        }
                    }
    puts("LOSE");
    return 0;
}

T4スター(星印)
  セグメントツリータイトルテンプレート走査線(カウントウインドウスターの境界)
  複雑\(O(N \ログN )\)

#include<bits/stdc++.h>
using namespace std;
int x[100005];
struct Line
{
    int l,r,h,val;
    friend bool operator < (Line a,Line b)
        {
            if(a.h==b.h) return a.val>b.val;
            return a.h<b.h;
        }
}li[100005];
struct SegTree
{
    int l,r,val,lazy;
}node[400005];
inline void pushup(int rt)
{
    node[rt].val=max(node[rt<<1].val,node[rt<<1|1].val);
}
inline void pushdown(int rt)
{
    if(node[rt].lazy)
    {
        node[rt<<1].lazy+=node[rt].lazy;
        node[rt<<1|1].lazy+=node[rt].lazy;
        node[rt<<1].val+=node[rt].lazy;
        node[rt<<1|1].val+=node[rt].lazy;
        node[rt].lazy=0;
    }
}
inline void build(int rt,int l,int r)
{
    node[rt].l=l,node[rt].r=r;
    node[rt].val=node[rt].lazy=0;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
}
inline void update(int rt,int fr,int to,int l,int r,int val)
{
    if(fr<=l&&to>=r)
    {
        node[rt].val+=val;
        node[rt].lazy+=val;
        return;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(fr<=mid) update(rt<<1,fr,to,l,mid,val);
    if(to>mid) update(rt<<1|1,fr,to,mid+1,r,val);
    pushup(rt);
}
inline int query(int rt,int fr,int to,int l,int r)
{
    if(fr<=l&&to>=r)
        return node[rt].val;
    pushdown(rt);
    int mid=(l+r)>>1,ans=0;
    if(fr<=mid) ans=query(rt<<1,fr,to,l,mid);
    if(to>mid) ans=max(ans,query(rt<<1|1,fr,to,mid+1,r));
    return ans;
}
int cnt;
int main()
{
    freopen("stars.in","r",stdin);
    freopen("stars.out","w",stdout);
    int t,n,W,H,xx,y,z;
    //scanf("%d",&t);
    //while(t--)
    //{
        scanf("%d%d%d",&n,&W,&H);
        cnt=0;
        for(int i=1;i<=n;++i)
        {
            scanf("%d%d%d",&xx,&y,&z);
            li[++cnt].l=xx,li[cnt].r=xx+W,li[cnt].h=y,li[cnt].val=z,x[cnt]=xx;
            li[++cnt].l=xx,li[cnt].r=xx+W,li[cnt].h=y+H,li[cnt].val=-z,x[cnt]=xx+W;
        }
        sort(li+1,li+cnt+1);
        sort(x+1,x+cnt+1);
        build(1,1,cnt);
        int maxx=-0x3f3f3f3f,tx=unique(x+1,x+cnt+1)-x-1;
        for(int i=1;i<=cnt;++i)
        {
            li[i].l=lower_bound(x+1,x+tx+1,li[i].l)-x;
            li[i].r=lower_bound(x+1,x+tx+1,li[i].r)-x;
            update(1,li[i].l,li[i].r,1,cnt,li[i].val);
            maxx=max(maxx,node[1].val);
        }
        printf("%d\n",maxx);
        //}
    return 0;
}

7.23 2日目のバースト数ゼロ奇妙なことは、受信された
T1のカウント
  イタリアこと:所与\(n-は\)ポイント、\(m個\)図に縁無し。定義から(私は\)\のポイント\(J \)パスポイントのコストは右パス上のすべてのエッジの辺の最大値です。\(私は\)する(j個の\を)\コストがjのパスに、iの全ての最小コストとして定義されます。
  私はどのように多くの尋ねた\(1≤i<j≤n\)を満たすには、\(私は\)がする\(j個\)を正確に費用\(X- \) 確保\(N- \ ^ {5} \のLeq 10)、\ (m個の\のLeq 3 * 10 ^ \ {5})、\ (X \のLeq 10 ^ {9} \)
  溶液:に変換未満(\ X \)マイナス未満\(X \)対数。統計DFSは、直接再要求ブロックユニコム\(C_ {N} ^ { 2} \) のように見える
  複雑\(O(N)\)

#include<bits/stdc++.h>
using namespace std;
#define maxn 300005
struct Edge
{
    int fr,to,val;
}eg[maxn<<1];
int edgenum,cnt,vis[maxn],head[maxn],fr[maxn],to[maxn],val[maxn];
long long num[maxn];
inline void add(int fr,int to,int val)
{
    eg[++edgenum].fr=head[fr];
    eg[edgenum].to=to;
    eg[edgenum].val=val;
    head[fr]=edgenum;
}
inline void dfs(int rt)
{
    vis[rt]=1;
    for(int i=head[rt];i;i=eg[i].fr)
    {
        if(vis[eg[i].to]) continue;
        vis[eg[i].to]=1;
        ++num[cnt];
        dfs(eg[i].to);
    }
}
int main()
{
    freopen("xdis.in","r",stdin);
    freopen("xdis.out","w",stdout);
    int n,m,x;
    long long ans=0;
    scanf("%d%d%d",&n,&m,&x);
    for(int i=1;i<=m;++i)
        scanf("%d%d%d",&fr[i],&to[i],&val[i]);
    for(int i=1;i<=m;++i)
        if(val[i]<=x) add(fr[i],to[i],val[i]),add(to[i],fr[i],val[i]);
    for(int i=1;i<=n;++i)
        if(!vis[i])
        {
            ++num[++cnt];
            dfs(i);
        }
    for(int i=1;i<=cnt;++i)
        ans+=(num[i]-1)*(num[i])/2;
    for(int i=1;i<=edgenum;++i)
        eg[i].fr=eg[i].to=eg[i].val=0;
    cnt=edgenum=0;
    memset(head,0,sizeof(head));
    memset(num,0,sizeof(num));
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=m;++i)
        if(val[i]<x) add(fr[i],to[i],val[i]),add(to[i],fr[i],val[i]);
    for(int i=1;i<=n;++i)
        if(!vis[i])
        {
            ++num[++cnt];
            dfs(i);
        }
    for(int i=1;i<=cnt;++i)
        ans-=(num[i]-1)*(num[i])/2;
    printf("%lld\n",ans);
    return 0;
}

T2問題ツリー(木)
  質問面は:によるものがある\(N \)無根ツリーポイントは、この構成\を(N \)我々が作成することができ、ルートノードと、それぞれ点\を(N \)木根ざした木。そこ\(q個\)問い合わせ番目、それぞれ与えられた2つの点を求めて\(\)\(B \) 私たちがいることを知りたい\(N \)根付いツリー、どのように多くの木満たします\(\)がされている(Bの\)\祖先または\(B \)されている\(\)祖先のを。確保\(N、Q \のLeq * 2 ^ {10}。5 \)を
  溶液:まず、ルート場合には、各ノードで再びDFSサイズを模索します。二人は、その後、直接添加サイズの任意の2つのノードをLCAされていない場合(私は、診察室で間違って押しての残りの部分を立ち上げを置きます)
  他の場合には、設定された\(X、Y \)は、 2つのノードXと深く調べられます。私たちは、検索したいチェーン意味息子のyのyの次の作品へのxは、Zに設定されています。答えが等しい\(N -サイズ[Z] +サイズ[X]を\) ので\(Zの\)上記と\(X \)(Xを含む)について明確にすべてのポイントの要件を満たします。
  複雑\(O(N \ログN )\)

#include<bits/stdc++.h>
using namespace std;
#define maxn 200005
int n,q;
struct Edge
{
    int fr,to;
}eg[maxn<<1];
int head[maxn],edgenum;
int top[maxn],size[maxn],son[maxn],id[maxn],fa[maxn],deep[maxn];
inline void add(int fr,int to)
{
    eg[++edgenum].fr=head[fr];
    eg[edgenum].to=to;
    head[fr]=edgenum;
}
inline int lca(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        x=fa[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    return x;
}
inline int llca(int x,int y)
{
    int last;
    if(deep[x]>deep[y]) swap(x,y);
    while(top[x]!=top[y]) last=y,y=fa[top[y]];
    if(x!=y) return son[x];
    return top[last];
}
inline int getans(int x,int y)
{
    int tmp=lca(x,y);
    if(tmp!=x&&tmp!=y) return size[x]+size[y];
    if(tmp==x) return n-size[llca(x,y)]+size[y];
    return n-size[llca(x,y)]+size[x]; 
}
inline void dfs1(int rt,int fat,int dep)
{
    size[rt]=1;
    fa[rt]=fat;
    deep[rt]=dep;
    int tmp,maxson=-1;
    for(int i=head[rt];i;i=eg[i].fr)
    {
        tmp=eg[i].to;
        if(tmp==fat) continue;
        dfs1(tmp,rt,dep+1);
        size[rt]+=size[tmp];
        if(size[tmp]>maxson)
            maxson=size[tmp],son[rt]=tmp;
    }
}
int cnt;
inline void dfs2(int rt,int topp)
{mindis(s1,t1)≤l1&&mindis(s2,t2)≤l2
    id[rt]=++cnt;
    top[rt]=topp;
    if(!son[rt]) return;
    dfs2(son[rt],topp);
    for(int i=head[rt];i;i=eg[i].fr)
        if(eg[i].to!=fa[rt]&&eg[i].to!=son[rt])
            dfs2(eg[i].to,eg[i].to);
}
int main()
{
    freopen("tree.in","r",stdin);
    freopen("tree.out","w",stdout);
    scanf("%d%d",&n,&q);
    int u,v;
    for(int i=1;i<n;++i)
    {
        scanf("%d%d",&u,&v);
        add(u,v),add(v,u);
    }
    dfs1(1,0,1);
    dfs2(1,1);
    for(int i=1;i<=q;++i)
    {
        scanf("%d%d",&u,&v);
        printf("%d\n",getans(u,v));
    }
    return 0;
}

T3イベント(パーティ)
  イタリアこと:所与\(N- \)ポイント\(m個\)側は無向グラフを接続し、所与のエッジのエッジ加重\(S1、T1、L1、 S1、T2、L2 \ 、適合することが求めで\(mindis(S1、T1)を \当量L1 \&\&mindis(S2、T2)\当量L2 \) 壊れた状態で辺の数まで。確保\(N、Mの\の当量3000
\)   ソリューション:変換がどのように多くの側面の最小値を必要とします。二つの最短経路に重ならない場合は、直接2つの長さを追加すること。さもなければ列挙交差点\(I、J \) エッジの最小数を更新します。辺の数はそうめったにspfaを使用しないので。(この質問は3倍遅いdijskra SPFAの比である)
  複雑\(O(N ^ {2 })\)

#include<bits/stdc++.h>
using namespace std;
#define maxn 3005
#define mp make_pair
#define pa pair<int,int>
struct Edge
{
    int fr,to,val;
}eg[maxn<<1];
int head[maxn],edgenum,n,m,dis[maxn][maxn],vis[maxn];
int s1,t1,l1,s2,t2,l2;
inline void add(int fr,int to)
{
    eg[++edgenum].fr=head[fr];
    eg[edgenum].to=to;
    eg[edgenum].val=1;
    head[fr]=edgenum;
}
inline void spfa(int st)
{
    queue<int> q;
    memset(vis,0,sizeof(vis));
    q.push(st);
    dis[st][st]=0;
    vis[st]=1;
    int tmp;
    while(!q.empty())
    {
        tmp=q.front();
        q.pop();
        vis[tmp]=0;
        for(int i=head[tmp];i;i=eg[i].fr)
        {
            if(dis[st][eg[i].to]>dis[st][tmp]+eg[i].val)
            {
                dis[st][eg[i].to]=dis[st][tmp]+eg[i].val;
                if(!vis[eg[i].to])
                {
                    vis[eg[i].to]=1;
                    q.push(eg[i].to);
                }
            }
        }
    }
}
inline void cmin(int& a,int b)
{
    a=min(a,b);
}
int main()
{
    freopen("party.in","r",stdin);
    freopen("party.out","w",stdout);
    scanf("%d%d",&n,&m);
    int u,v;
    for(int i=1;i<=m;++i)
    {
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    scanf("%d%d%d%d%d%d",&s1,&t1,&l1,&s2,&t2,&l2);
    memset(dis,0x3f,sizeof(dis));
    for(int i=1;i<=n;++i)
        spfa(i);
    if(dis[s1][t1]>l1||dis[s2][t2]>l2)
    {
        puts("That's all trouble!");
        return 0;
    }
    int ans=dis[s1][t1]+dis[s2][t2];
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
        {
            if(dis[s1][i]+dis[i][j]+dis[j][t1]<=l1&&dis[s2][i]+dis[i][j]+dis[j][t2]<=l2)
                cmin(ans,dis[s1][i]+dis[s2][i]+dis[i][j]+dis[j][t1]+dis[j][t2]);
            if(dis[s1][j]+dis[j][i]+dis[i][t1]<=l1&&dis[s2][i]+dis[i][j]+dis[j][t2]<=l2)
                cmin(ans,dis[s1][j]+dis[j][i]+dis[i][t1]+dis[s2][i]+dis[j][t2]);
        }
    printf("%d\n",m-ans);
    return 0;
}

T4スパニングツリー最小(グラフ) 
 イタリアその:\(N- \)点、\(M \)操作、\(AB&追加\)を表す\を(B \)右辺との間は、現在の作業番号に接続されています。側、\は(削除K \)図最大で右側を示す\(K \)を削除エッジ\(リターン\)は、最後の操作の離脱を表します。右側には、各操作と現在の最小スパニングツリーの後に得られます。
  最小スパニングツリーは、出力0は存在しません。最初は保証されない(リターン\)\ \、 リターン\)が付いていない\(リターン\) 図中のエッジの現在の数が以上のK \(N- \ 1当量3. 5 * 10 ^ {}、M \ 1当量5 5×10 ^ {} \)
  ソリューション:永続LCT
問題を直接Kuaiのシニア・ソリューション(私はないので、。):データ構造愚かな学校の生徒が硬化
:参照してください公式の説明でセクションポイントを解釈は、
削除された側に参加する最後です;のみ、前に戻り右側が増加している:この質問は、比較的強い性質でありますバージョンは
性質が強いので、おそらく解決策は比較的簡単であるため、これらの特性がなければ持続的な動的な木である必要は?かもしれませんが
インクリメンタル側が右、片側がオンに滞在されますので、最小スパニングツリーが削除されるまで。
全て削除のため最大側辺の重みは、最小スパニングツリーの他方の側に特定のエッジの後が削除される心配しないでください。
ボーダー消去動作をサポートするために使用することができ、ランクに応じてマージ互いに素-セットは、トップダウン枠消しので、サブツリーのサイズも容易に維持することができます。
唯一の問題点は、操作をキャンセルすることで、巧妙な方法で解決することができます。
この問題は、力ではないので、各操作がどのような次の動作タイプを知ることができるとき。

  • それは、その後プラス側に引き出される場合は、このプロセスをシミュレートすることができ、複雑さが影響を受けません。
    エッジは削除してから取り消される場合は、これらのエッジを削除する必要はありません、これらの出力側に答える直接参加していない(つまり、レコードを意味します答えたびに)
    あることに注意する場所の詳細の一部は、そのような削除した後に\(k個\)がよりエッジ\(k個\)スパニングツリーの側にストリップ。

コード?まずグー


  • 7.25 3日目はゼロLSTバースト姉妹校負帰還大きなサンプル連続タムD祭を与えない奇妙なものの一部(霧)のを
  • 7.26 Day4はゼロ数学的な神々が大きなサンプル悪い不滅の質問に話題Jiechaiのコメントを与えていないバースト

おすすめ

転載: www.cnblogs.com/123789456ye/p/11299247.html