BZOJ 3832: [Poi2014]Rally

Sol

线段树+拓扑序.

先把图的拓扑序搞出来,然后统计从起点到该点最长链,从该点到终点的最长链,然后建个起点终点,这里跟网络流很像,把它统一到一个有起点的图中,这里也要注意下细节处理.S,T的一个边割掉后最长链就是答案.

然后一开始所有点都在T的集合中,一个个将点加入S集合,用线段树维护每个节点 (从起点到该点最长链+从终点到该点的最长链)的长度,其实就是一个权值线段树,然后就是加加减减的...

Code

/**************************************************************
    Problem: 3832
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:13472 ms
    Memory:65804 kb
****************************************************************/

#include<cstdio>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;

const int N = 500050;
#define debug(a) cout<<#a<<"="<<a<<endl

inline int in(int x=0,char ch=getchar()){ while(ch>‘9‘||ch<‘0‘) ch=getchar();
    while(ch>=‘0‘&&ch<=‘9‘) x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar();return x; }

int n,m,l,r,s,t;int du[N],q[N],f[N][2];
vector<int> g[N],h[N];
int ans1,ans2;

#define mid ((l+r)>>1)
#define lc (o<<1)
#define rc (o<<1|1)

int d[N<<2],ma[N<<2];
void Add(int x,int v,int o=1,int l=0,int r=n+2){
    if(l==r){ d[o]+=v;return; }
    if(x<=mid) Add(x,v,lc,l,mid);
    else Add(x,v,rc,mid+1,r);
    d[o]=d[lc]+d[rc];
}
int Query(int o=1,int l=0,int r=n+2){
    if(l==r) return l;
    if(d[rc]>0) return Query(rc,mid+1,r);
    else return Query(lc,l,mid);
}

#undef mid
#undef lc
#undef rc

int main(){
//  freopen("in.in","r",stdin);
    n=in(),m=in();
    for(int i=1,u,v;i<=m;i++){
        u=in(),v=in(),du[v]++;
        g[u].push_back(v),h[v].push_back(u);
    }
    for(int i=1;i<=n;i++) if(!du[i]) q[r++]=i;
    int cnt=r;
    for(int x;l<r;){
        x=q[l++];
        for(int i=0,lim=g[x].size();i<lim;i++) if(!--du[g[x][i]]) q[r++]=g[x][i];
    }for(int i=0;i<n;i++){
        for(int j=0,u=q[i],lim=h[u].size();j<lim;j++)
            f[u][0]=max(f[u][0],f[h[u][j]][0]+1);
        for(int j=0,u=q[r-i-1],lim=g[u].size();j<lim;j++)
            f[u][1]=max(f[u][1],f[g[u][j]][1]+1);
    }

//  for(int i=0;i<cnt;i++) Add(f[q[i]][1],1);
//  debug(cnt);
//  debug(Query());

    s=n+1,t=s+1;
    for(int i=1;i<=n;i++){
        g[s].push_back(i),h[i].push_back(s);
        g[i].push_back(t),h[t].push_back(i);
        Add(f[i][1],1);
    }
    f[s][0]=-1,f[t][1]=-1;
    ans2=n+2;

//  for(int i=1;i<=t;i++) printf("%d %d\n",f[i][0],f[i][1]);

    for(int i=0;i<n;i++){
        int u=q[i];
        for(int j=0,lim=h[u].size();j<lim;j++)
            Add(f[h[u][j]][0]+f[u][1]+1,-1);
        int tmp=Query();
        if(tmp<ans2) ans2=tmp,ans1=u;
        for(int j=0,lim=g[u].size();j<lim;j++)
            Add(f[g[u][j]][1]+f[u][0]+1,1);
    }return printf("%d %d\n",ans1,ans2);
}

  

时间: 2024-12-21 08:58:33

BZOJ 3832: [Poi2014]Rally的相关文章

bzoj 3832: [Poi2014]Rally(线段树+拓扑排序)

3832: [Poi2014]Rally Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special Judge Submit: 113  Solved: 56 [Submit][Status][Discuss] Description An annual bicycle rally will soon begin in Byteburg. The bikers of Byteburg are natural long distance cyclis

【刷题】BZOJ 3832 [Poi2014]Rally

Description An annual bicycle rally will soon begin in Byteburg. The bikers of Byteburg are natural long distance cyclists. Local representatives of motorcyclists, long feuding the cyclists, have decided to sabotage the event. There are intersections

BZOJ 3524: [Poi2014]Couriers

3524: [Poi2014]Couriers Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1905  Solved: 691[Submit][Status][Discuss] Description 给一个长度为n的序列a.1≤a[i]≤n.m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2.如果存在,输出这个数,否则输出0. Input 第一行两个数n,m.第二行n个数,a[i].接下来m行,

bzoj 3831: [Poi2014]Little Bird

3831: [Poi2014]Little Bird Description In the Byteotian Line Forest there are   trees in a row. On top of the first one, there is a little bird who would like to fly over to the top of the last tree. Being in fact very little, the bird might lack the

BZOJ 3524: [Poi2014]Couriers( 主席树 )

卡我空间.... 这道题应该是主席树入门题...无修改 , 离散化都不用...出题人业界良心啊 一开始的空白树我 build 出来结果就多了整整 2n 个 Node , 然后就 MLE 了... ( 双倍经验 , 另一道见上图 ) ---------------------------------------------------------------------------------------------- #include<cstdio> #include<cstring&g

BZOJ 3827: [Poi2014]Around the world

Sol 并查集. 一个点所能到达的最远是单调不降的.然后将链延长到两倍,预处理出每个点到达的最远点,然后倒着计算深度. 再然后一直跳,跳到>=x+n的点,因为跳到的点都能到最终的点,并且不影响后面的答案. Code /************************************************************** Problem: 3827 User: BeiYu Language: C++ Result: Accepted Time:70156 ms Memory:

bzoj 3522: [Poi2014]Hotel

呵呵,一开始天真的我以为求个 西格玛 C(??,3)就好了.. (题解:比枚举2个数的再多一个,,一样搞) 1 #include <bits/stdc++.h> 2 #define LL long long 3 #define lowbit(x) x&(-x) 4 #define inf 1e15 5 using namespace std; 6 inline int ra() 7 { 8 int x=0,f=1; char ch=getchar(); 9 while (ch<'

bzoj 3526 : [Poi2014]Card

把每张卡牌看成两个点,裸的线段树维护连通性. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define ls x*2,l,mid 6 #define rs x*2+1,mid+1,r 7 #define N 200005 8 using namespace std; 9 int read() 10 { 11 char c=getcha

BZOJ 3834 [Poi2014]Solar Panels 数学

题意: n组询问,每次问smin<=x<=smax, wmin<=y<=wmax时gcd(x, y)的最大值. 解析: md以前有个结论忘了结果这题坑我30分钟+ 我们显然可以找到一个结论. 令gcd(x,y)=z; 那么显然有(smin-1)/z #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace