cantaloupebulid by [参赛达人]哈密瓜 at 2018-08-14 20:50
Rating:1945

1.建图

2.数字哈希

3.树分块

4.二分图最大匹配匈牙利算法

5.普通线段树

6.普通并查集

8.树链剖分(点权)

9.最小公倍数&最小公约数

10.树链剖分(边权)

11.组合数打表(求大量组合数)

12.费用流

13.伸展树


以下内容于[2018-08-23 21:13:22]补充

14.最大流

1 reply by [参赛达人]哈密瓜 at 2018-08-14 20:53
Rating:1945
const int maxn = 200000 + 10;
int n, m, first[maxn], sign;
struct Edge {
    int to, w, next;
} edge[maxn << 2];
void init() {
    memset(first, -1, sizeof(first));
    sign = 0;
}
void add_edge(int u, int v, int w) {
    edge[sign].to = v;
    edge[sign].w = w;
    edge[sign].next = first[u];
    first[u] = sign++;
}


2 reply by [参赛达人]哈密瓜 at 2018-08-15 01:22
Rating:1945

inline void insert_hash(int num)

{

    int key=num%MOD;

    while(hash[key])

    {

        key++;

        key%=MOD;

    }

    hash[key]=num;

}


inline int find_hash(int num)

{

    int key =num%MOD;

    while(hash[key])

    {

        if(hash[key]==num)

            return 1;

        key++;

        key%=MOD;

    }

    return 0;

}


3 reply by [参赛达人]哈密瓜 at 2018-08-15 15:49
Rating:1945
///树分块
int top = 0,st[maxn],belong[maxn],root,b;
void dfs(int now)
{
    int now_top = top;
    for(int i = first[now]; ~i; i = edge[i].next)
    {
        int to = edge[i].to;
        dfs(to);
        if(top-now_top >= b)  ///stack内元素大于b出栈
        {
            ++type;
            while(top!=now_top)
            {
                belong[st[top--]] = root;
            }
        }
    }
    st[++top] = now;
}
int main()
{
    b = sqrt(n);
    type = 0;
    dfs(1);
    while(top)belong[st[top--]] = root; ///stack内剩余元素加入最后一个块中
    return 0;
}


4 reply by [参赛达人]哈密瓜 at 2018-08-15 15:57
Rating:1945
///二分图匈牙利算法 时间复杂度O(n*m),空间复杂度,O(n*m)
int nx,ny;
bool bmap[maxn][maxn];  ///图
bool bmask[maxn];
int cx[maxn],cy[maxn];
int findpath(int u)
{
    int i,j;
    for(int i=1; i<=ny; i++)
    {
        if(bmap[u][i]&&!bmask[i])
        {
            bmask[i]=1;
            if(cy[i]==-1||findpath(cy[i]))
            {
                cy[i]=u;
                cx[u]=i;
                return 1;
            }
        }
    }
    return 0;
}

int MaxMatch(int n,int m)
{

    int res=0;
    nx = n,ny = m;
    for(int i=0; i<maxn; i++)
        cx[i]=-1,cy[i]=-1;
    memset(bmask,0,sizeof(bmask));
    for(int i=1; i<=nx; i++)
    {
        if(cx[i]==-1)
        {
            for(int j=1; j<=ny; j++)
                bmask[j]=0;
            res+=findpath(i);
        }
    }
    return res;
}


5 reply by [参赛达人]哈密瓜 at 2018-08-15 16:10
Rating:1945
///普通线段树
struct node
{
    int l,r;
    ll sum,lazy;
} T[maxn*4];
ll ans=0,a[maxn];
void build(int v,int l,int r)
{
    T[v].l=l,T[v].r=r,T[v].lazy = 0;
    if(l==r)
    {
        T[v].sum=a[l];
        return ;
    }
    int mid = (l+r)>>1;
    build(v<<1,l,mid);
    build(v<<1|1,mid+1,r);
    T[v].sum = T[v<<1].sum+T[v<<1|1].sum;
}
void add(int v,int l,int r,ll value)
{
    if(T[v].l==l&&T[v].r==r)
    {
        T[v].sum+=value*(r-l+1);
        T[v].lazy+=value;
        return ;
    }
    int mid=(T[v].l+T[v].r)>>1;
    if(T[v].lazy)
    {
        T[v<<1].sum += T[v].lazy * (T[v<<1].r - T[v<<1].l + 1);
        T[v<<1|1].sum += T[v].lazy * (T[v<<1|1].r - T[v<<1|1].l + 1);
        T[v<<1].lazy += T[v].lazy;
        T[v<<1|1].lazy += T[v].lazy;
        T[v].lazy=0;
    }
    if(r<=mid)
    {
        add(v<<1,l,r,value);
    }
    else
    {
        if(l>mid)
        {
            add(v<<1|1,l,r,value);
        }
        else
        {
            add(v<<1,l,mid,value);
            add(v<<1|1,mid+1,r,value);
        }
    }
    T[v].sum = T[v<<1].sum+T[v<<1|1].sum;
}

void query(int v,int l,int r)
{
    if(T[v].l==l&&T[v].r==r)
    {
        ans += T[v].sum;
        return ;
    }
    int mid=(T[v].l+T[v].r)>>1;
    if(T[v].lazy)
    {
        T[v<<1].sum += T[v].lazy * (T[v<<1].r - T[v<<1].l + 1);
        T[v<<1|1].sum += T[v].lazy * (T[v<<1|1].r - T[v<<1|1].l + 1);
        T[v<<1].lazy += T[v].lazy;
        T[v<<1|1].lazy += T[v].lazy;
        T[v].lazy=0;
    }
    if(r<=mid)
    {
        query(v<<1,l,r);
    }
    else
    {
        if(l>mid)
        {
            query(v<<1|1,l,r);
        }
        else
        {
            query(v<<1,l,mid);
            query(v<<1|1,mid+1,r);
        }
    }
    T[v].sum = T[v<<1].sum+T[v<<1|1].sum;
}


6 reply by [参赛达人]哈密瓜 at 2018-08-15 17:08
Rating:1945
///普通并查集
int father[maxn];
void make_set(int n)
{
    for(int i=0; i<=n; i++)father[i]=i;
}
int Find(int x)
{
    int p,tmp;
    p = x;
    while(x != father[x])
        x = father[x];
    while(p!=x)
    {
        tmp = father[p];
        father[p] = x;
        p = tmp;
    }
    return x;
}
int isSome(int x,int y)
{
    if(Find(x)==Find(y))
    {
        return 1;
    }
    return 0;
}
int Union(int x,int y)
{
    int rx=Find(x),ry=Find(y);
    if(rx!=ry)
    {
        father[rx]=ry;
    }
}


7
此处有一条回复被隐藏
8 reply by [参赛达人]哈密瓜 at 2018-08-17 16:17
Rating:1945
///树链剖分
int tim=0;
int pos[N];   ///用来保存当前节点在线段树中的位置;
int deep[N];  ///用来保存当前节点的深度;
int tid[N];   ///用来保存树中每个节点剖分后的新编号;
int son[N];   ///用来保存重儿子;
int top[N];   ///用来保存当前节点的所在链的顶端节点;
int size[N];  ///用来保存以x为根的子树节点个数;
int fa[N];    ///用来保存当前节点的父亲;
long long begi[N];  ///按树原来编号元素值

//建图
int first[N], sign;
void init()
{
    memset(first, -1, sizeof(first));
    sign = 0;
}
void add_edge(int u, int v)
{
    edge[sign].to = v;
    edge[sign].next = first[u];
    first[u] = sign++;
}

//两次dfs
void dfsfir(int u,int father,int dep)
{
    fa[u]=father;
    deep[u]=dep;
    size[u]=1;
    for(int i=first[u]; ~i; i=edge[i].next)
    {
        int v=edge[i].to;
        if(v!=father)
        {
            dfsfir(v,u,dep+1);
            size[u]+=size[v];
            if(son[u]==0||size[v]>size[son[u]])son[u]=v;
        }
    }
}
void dfsec(int u,int tp)
{
    top[u]=tp;
    tid[u]=++tim;
    pos[tid[u]]=u;
    if(son[u]==0)return;
    dfsec(son[u],tp);
    for(int i=first[u]; ~i; i=edge[i].next)
    {
        int v=edge[i].to;
        if(v!=fa[u]&&v!=son[u])dfsec(v,v);
    }
}

//查询和
///路径上点权和
long long findSum(int x,int y)
{
    long long sum=0;
    int fx,fy;
    fx=top[x];
    fy=top[y];
    while(fx!=fy)//不在一条重链上,即非连续一段区间
    {
        if(deep[fx]<deep[fy])
        {
            swap(fx,fy);
            swap(x,y);
        }
        sum=(sum+QuerySum(1,tid[fx],tid[x]));
        x=fa[fx];
        fx=top[x];
    }
    if(deep[x]>deep[y]) swap(x,y);//同一条重链
    return sum=(sum+QuerySum(1,tid[x],tid[y]));
}


///区间更新
void treeUpdate(int x,int y,int z)
{
    int fx,fy;
    fx=top[x];
    fy=top[y];
    while(fx!=fy)//不在一条重链上,即非连续一段区间
    {
        if(deep[fx]<deep[fy])
        {
            swap(fx,fy);
            swap(x,y);
        }
        add(1,tid[fx],tid[x],z);
        x=fa[fx];
        fx=top[x];
    }
    if(deep[x]>deep[y]) swap(x,y);//同一条重链
    add(1,tid[x],tid[y],z);
}

///线段树建树
void build(int v,int l,int r)
{
    /*
    */
    if(l==r)
    {
        T[v].Max =  T[v].sum = begi[pos[l]];
        return ;
    }
    /*
    */
}

int main()
{
    ///************
    dfsfir(1,0,1);
    dfsec(1,1);
    ///************
    ///更新x的值为y
    ///update(1,tid[x],y);
}


9 reply by [参赛达人]哈密瓜 at 2018-08-17 21:18
Rating:1945
///最小公倍数&最小公约数
ll GCD(ll a,ll b)
{
    return b==0?a:GCD(b,a%b);
}

ll LCM(ll a,ll b)
{
    return a*b/GCD(a,b);
}


10 reply by [参赛达人]哈密瓜 at 2018-08-18 21:02
Rating:1945
///树链剖分 边权
int son[maxn]; //表示该点重链的子节点
int num[maxn]; //表示以该点为根的子树的节点数量
int dep[maxn]; //表示该节点的深度
int fa[maxn];  //表示该节点的父亲节点
int vis[maxn]; //表示该节点在线段树中的编号
int top[maxn]; //表示这条重链的顶端节点
int edge[maxn][3];
int now;

void dfs1(int u,int v,int step)    //第一遍dfs求出son,fa,num,dep
{
    dep[v]=step,num[v]=1,fa[v]=u;
    for(int i=first[v]; ~i; i=edge1[i].next)
    {
        int to=edge1[i].to;
        if(to!=u)
        {
            dfs1(v,to,step+1);
            num[v]+=num[to];
            if(son[v]==-1||num[son[v]]<num[to])
            {
                son[v]=to;
            }
        }
    }
}
void dfs2(int u,int v)         // 第二遍dfs求出top和vis
{
    top[v]=u,vis[v]=now++;
    if(son[v]==-1)
        return ;
    else
        dfs2(u,son[v]);
    for(int i=first[v]; ~i; i=edge1[i].next)
    {
        int to = edge1[i].to;
        if(to==fa[v]||to==son[v])
            continue;
        dfs2(to,to);
    }
}

int Find(int y,int z)
{
    int q,w;
    int ans = 0;
    q = top[y],w = top[z];
    int f=0;
    while(q != w)         //不在一条重链上,就爬树
    {
        if(dep[q] < dep[w])
            swap(q,w),swap(y,z);
        if(f==0)
        {
            ans = query(1,vis[q]+1,vis[y]+1);
            f=1;
        }
        else
            ans = max(ans,query(1,vis[q]+1,vis[y]+1));
        y = fa[q];
        q = top[y];
    }
    if(y != z)            //爬到一条重链上
    {
        if(dep[y] > dep[z])
            swap(y,z);
        if(f==0)
        {
            ans = query(1,vis[son[y]]+1,vis[z]+1);
            f=1;
        }
        else
            ans = max(ans,query(1,vis[son[y]]+1,vis[z]+1));
    }
    return ans;
}

void update(int y,int z)
{
    int q,w;
    q = top[y],w = top[z];
    while(q != w)         //不在一条重链上,就爬树
    {
        if(dep[q] < dep[w])
            swap(q,w),swap(y,z);
        update1(1,vis[q]+1,vis[y]+1);
        y = fa[q];
        q = top[y];
    }
    if(y != z)            //爬到一条重链上
    {
        if(dep[y] > dep[z])
            swap(y,z);
        update1(1,vis[son[y]]+1,vis[z]+1);
    }
}

void init()
{
    now=0;
    memset(son,-1,sizeof(son));
    memset(tree,0,sizeof(tree));
}

int main()
{
    init();
    init_edge();
    scanf("%d",&n);
    for(int i=1; i<=n-1; i++)
    {
        scanf("%d%d%d",&edge[i][0],&edge[i][1],&edge[i][2]);
        add_edge(edge[i][0],edge[i][1],edge[i][2]);
        add_edge(edge[i][1],edge[i][0],edge[i][2]);
    }
    dfs1(1,1,1);
    dfs2(1,1);
    build(1,1,n);
    for(int i = 1; i <= n-1; i++)
    {
        if(dep[edge[i][0]] < dep[edge[i][1]])
            swap(edge[i][0],edge[i][1]);
        update2(1,vis[edge[i][0]]+1,edge[i][2]);
    }

    ///区间查询,更新
    printf("%d\n",Find(l,r));
    update(l,r);
}


回复
要回复,请先登录

T^T Online Judge

[BUG反馈] [FAQ] [闽ICP备17026590号-1]
当前版本:3.24 系统时间: