码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1224 HNOI2002 彩票 DFS

时间:2014-11-21 16:17:02      阅读:285      评论:0      收藏:0      [点我收藏+]

标签:bzoj   bzoj1224   dfs   

题目大意:在1~m中选n个不同的数 要求和为X/Y 求方案数

爆搜的话应该是100E左右 所以考虑加剪枝

上下界剪枝 如果当前的情况下剩余的数最大都无法到达目标或最小都无法小于目标 则剪枝

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 200200
using namespace std;
struct Segtree{
    Segtree *ls,*rs;
    int num;
    void* operator new (size_t size,Segtree *_,Segtree *__,int ___);
}*tree[M],*mempool,*C;
struct edge{
    int x,y,f;
    bool operator < (const edge &Y) const
    {
        return f < Y.f ;
    }
}edges[500500];
struct abcd{
    int to,next;
}table[M];
int head[M],tot;
int n,m,q,ans;
int a[M],fa[M][20],dis[M][20],belong[M];
int seq[M],l[M],r[M],cnt;
void* Segtree :: operator new (size_t size,Segtree *_,Segtree *__,int ___)
{
    if(C==mempool)
    {
        C=new Segtree[1<<15];
        mempool=C+(1<<15);
    }
    C->ls=_;
    C->rs=__;
    C->num=___;
    return C++;
}
void Add(int x,int y)
{
    table[++tot].to=y;
    table[tot].next=head[x];
    head[x]=tot;
}
int Find(int x)
{
    if(!belong[x]||belong[x]==x)
        return belong[x]=x;
    return belong[x]=Find(belong[x]);
}
void Kruskal()
{
    int i;
    sort(edges+1,edges+m+1);
    for(i=1;i<=m;i++)
    {
        int x=Find(edges[i].x);
        int y=Find(edges[i].y);
        if(x==y) continue;
        belong[x]=belong[y]=++n;
        fa[x][0]=fa[y][0]=n;
        dis[x][0]=dis[y][0]=edges[i].f;
        Add(n,x);Add(n,y);
        printf("%d %d\n",n,x);
        printf("%d %d\n",n,y);
        printf("%d[label=\"%d\",fontcolor=red]\n",n,edges[i].f);
    }
}
void DFS(int x)
{
    int i;
    seq[l[x]=++cnt]=a[x];
    for(i=head[x];i;i=table[i].next)
        DFS(table[i].to);
    r[x]=cnt;
}
Segtree* Build_Tree(Segtree *p,int x,int y,int val)
{
    int mid=x+y>>1;
    if(x==y) return new (0x0,0x0,p->num+1) Segtree;
    if(val<=mid) return new (Build_Tree(p->ls,x,mid,val),p->rs,p->num+1) Segtree;
    else return new (p->ls,Build_Tree(p->rs,mid+1,y,val),p->num+1) Segtree;
}
int Get_Kth(Segtree *p1,Segtree *p2,int x,int y,int k)
{
    int mid=x+y>>1;
    if(x==y) return mid;
    int temp=p2->rs->num-p1->rs->num;
    if(k<=temp) return Get_Kth(p1->rs,p2->rs,mid+1,y,k);
    else return Get_Kth(p1->ls,p2->ls,x,mid,k-temp);
}
int Get_Root(int x,int y)
{
    int j;
    for(j=19;~j;j--)
        if( fa[x][j] && dis[x][j]<=y )
            x=fa[x][j];
    return x;
}
int main()
{
    int i,j,v,x,k;
    cin>>n>>m>>q;
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(i=1;i<=m;i++)
        scanf("%d%d%d",&edges[i].x,&edges[i].y,&edges[i].f);
    Kruskal();
    for(j=1;j<=19;j++)
        for(i=1;i<=n;i++)
            fa[i][j]=fa[fa[i][j-1]][j-1],
            dis[i][j]=max(dis[i][j-1],dis[fa[i][j-1]][j-1]);
    DFS(n);
    tree[0]=new (0x0,0x0,0) Segtree;
    tree[0]->ls=tree[0]->rs=tree[0];
    for(i=1;i<=n;i++)
        tree[i]=Build_Tree(tree[i-1],0,1000000000,seq[i]);
    for(i=1;i<=q;i++)
    {
        scanf("%d%d%d",&v,&x,&k);
        //x^=ans;v^=ans;k^=ans;
        int root=Get_Root(v,x);
        if(r[root]-l[root]+1<k)
        {
            puts("-1");
            ans=0;
            continue;
        }
        ans=Get_Kth(tree[l[root]-1],tree[r[root]],0,1000000000,k);
        if(!ans)
        {
            puts("-1");
            continue;
        }
        printf("%d\n",ans);
    }
}


BZOJ 1224 HNOI2002 彩票 DFS

标签:bzoj   bzoj1224   dfs   

原文地址:http://blog.csdn.net/popoqqq/article/details/41349571

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!