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

NOI考前乱写

时间:2015-07-02 20:57:35      阅读:135      评论:0      收藏:0      [点我收藏+]

标签:

还有13天NOI,把各种乱七八糟的算法都重新过一遍还是比较有必要的。。。

 

技术分享
//HDU 5046 Airport
//DancingLink
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 110
#define MAXD MAXN*MAXN
#define INF 0x3f3f3f3f
#define LL "%lld"
typedef long long qword;
struct point
{
        qword x,y;
};
point pl[MAXN];
qword dis(point p1,point p2)
{
        return abs(p1.x-p2.x)+abs(p1.y-p2.y);
}
int L[MAXD],R[MAXD],U[MAXD],D[MAXD];
int ptr[MAXN];
int tot[MAXN];
int col[MAXD];
int topd=0;
int head=0;
void cover(int now)
{
        for (int i=R[now];i!=now;i=R[i])
        {
                for (int j=U[i];j!=i;j=U[j])
                {
                        L[R[j]]=L[j];
                        R[L[j]]=R[j];
                }
        }
        for (int j=U[now];j!=now;j=U[j])
        {
                L[R[j]]=L[j];
                R[L[j]]=R[j];
        }
}
void recover(int now)
{
        for (int i=R[now];i!=now;i=R[i])
                for (int j=U[i];j!=i;j=U[j])
                        L[R[j]]=R[L[j]]=j;
        for (int j=U[now];j!=now;j=U[j])
                L[R[j]]=R[L[j]]=j;
}
int vv[MAXN];
int ff()
{
        int ret=0;
        for (int i=R[head];i!=head;i=R[i])
                vv[col[i]]=true;
        for (int i=R[head];i!=head;i=R[i])
        {
                if (vv[col[i]])
                {
                        ret++;
                        for (int j=D[i];j!=i;j=D[j])
                        {
                                for (int k=R[j];k!=j;k=R[k])
                                {
                                        vv[col[k]]=false;
                                }
                        }
                }
        }
        return ret;
}
bool solve(int trst)
{
        if (L[head]==R[head] && L[head]==head)return true;
        if (!trst)return false;
        if (trst<ff())return false;
        pair<int,int> mnv=make_pair(INF,0);
        for (int i=R[head];i!=head;i=R[i])
                mnv=min(mnv,make_pair(tot[i],i));
        int now=mnv.second;
        for (int i=D[now];i!=now;i=D[i])
        {
                cover(i);
                if (solve(trst-1))return true;
                recover(i);
        }
        return false;
}

int main()
{
        freopen("input.txt","r",stdin);
        int nn;
        int n,m;
        int x,y,z;
        scanf("%d",&nn);
        int caseid=0;
        while (nn--)
        {
                caseid++;
                scanf("%d%d",&n,&m);
                for (int i=1;i<=n;i++)
                        scanf(LL LL ,&pl[i].x,&pl[i].y);
                memset(ptr,0,sizeof(ptr[0])*(n+10));
                memset(tot,0,sizeof(tot[0])*(n+10));
                qword l=-1,r=1ll<<33,mid;
                while (l+1<r)
                {
                        mid=(l+r)>>1;
                        topd=0;
                        head=++topd;
                        L[head]=R[head]=head;
                        for (int i=1;i<=n;i++)
                        {
                                int np=++topd;
                                col[np]=i;
                                R[np]=head;
                                L[np]=L[head];
                                L[R[np]]=np;
                                R[L[np]]=np;
                                D[np]=U[np]=np;
                                ptr[i]=np;
                        }
                        for (int i=1;i<=n;i++)
                        {
                                int last=0;
                                for (int j=1;j<=n;j++)
                                {
                                        if (dis(pl[i],pl[j])<=mid)
                                        {
                                                int np=++topd;
                                                col[np]=j;
                                                tot[ptr[j]]++;
                                                D[np]=ptr[j];
                                                U[np]=U[ptr[j]];
                                                D[U[np]]=U[D[np]]=np;
                                                if (!last)
                                                {
                                                        L[np]=R[np]=np;
                                                }else
                                                {
                                                        L[np]=last;
                                                        R[np]=R[last];
                                                        L[R[np]]=R[L[np]]=np;
                                                }
                                                last=np;
                                        }
                                }
                        }
                        if (solve(m))
                        {
                                r=mid;
                        }else
                        {
                                l=mid;
                        }
                }
                printf("Case #%d: "LL"\n",caseid,r);
        }
}
DancingLink

半年没写DLX了,还能在30分钟内写出来,感觉不错。

DLX分为精确覆盖和完全覆盖,两者的区别大概是在cover和recover之中。

另外DLX也是需要剪枝的。

 

技术分享
//bzoj 1135
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 210000
#define MAXT MAXN*5
#define lch (now<<1)
#define rch (now<<1^1)
#define smid ((l+r)>>1)
typedef long long qword;
struct sgt_node
{
        int lc,rc;
        qword lx,rx,mx;
        qword sum;
}sgt[MAXT];
void update(int now)
{
        sgt[now].lx=max(sgt[lch].lx,sgt[lch].sum+sgt[rch].lx);
        sgt[now].rx=max(sgt[rch].rx,sgt[rch].sum+sgt[lch].rx);
        sgt[now].sum=sgt[lch].sum+sgt[rch].sum;
        sgt[now].mx=max(max(sgt[lch].mx,sgt[rch].mx),sgt[lch].rx+sgt[rch].lx);
}
void Build_sgt(int now,int l,int r,int v)
{
        if (l==r)
        {
                sgt[now].sum=v;
                sgt[now].lx=sgt[now].rx=sgt[now].mx=v;
                return ;
        }
        Build_sgt(lch,l,smid,v);
        Build_sgt(rch,smid+1,r,v);
        update(now);
}
void Modify_sgt(int now,int l,int r,int pos,int v)
{
        if (l==r)
        {
                sgt[now].sum+=v;
                sgt[now].lx+=v;
                sgt[now].rx+=v;
                sgt[now].mx+=v;
                return ;
        }
        if (pos<=smid)
                Modify_sgt(lch,l,smid,pos,v);
        else
                Modify_sgt(rch,smid+1,r,pos,v);
        update(now);
}

int main()
{
        freopen("input.txt","r",stdin);
        int n,m,t,d;
        int x,y;
        scanf("%d%d%d%d",&n,&m,&t,&d);
        Build_sgt(1,1,n,-t);
        for (int i=0;i<m;i++)
        {
                scanf("%d%d",&x,&y);
                Modify_sgt(1,1,n,x,y);
                if (sgt[1].mx>(qword)t*d)
                {
                        printf("NIE\n");
                }else
                {
                        printf("TAK\n");
                }
        }
Hall

hall定理用于二分图匹配相关问题,在要求方案时用贪心或匈牙利算法,运用hall定理有利于优化时间复杂度。

 

NOI考前乱写

标签:

原文地址:http://www.cnblogs.com/mhy12345/p/4616949.html

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