NOI考前乱写

还有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"
",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
");
                }else
                {
                        printf("TAK
");
                }
        }
Hall

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

//bzoj 3270
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cassert>
#include<cmath>
using namespace std;
#define MAXN 1010
#define MAXV MAXN
#define MAXE MAXN*20
typedef double real;
const real eps = 1e-7;

struct Edge
{
        int np;
        Edge *next;
}E[MAXE],*V[MAXV];
int tope=-1;
void addedge(int x,int y)
{
        E[++tope].np=y;
        E[tope].next=V[x];
        V[x]=&E[tope];
}
real ps[MAXN];
real mat[MAXN][MAXN];
real res[MAXN];
int deg[MAXN];

int main()
{
        freopen("input.txt","r",stdin);
        int n,m;
        int a,b;
        int x,y,z;
        scanf("%d%d",&n,&m);
        scanf("%d%d",&a,&b);
        a--;b--;
        for (int i=0;i<m;i++)
        {
                scanf("%d%d",&x,&y);
                x--;y--;
                addedge(x,y);
                addedge(y,x);
                deg[x]++;
                deg[y]++;
        }
        for (int i=0;i<n;i++)
                scanf("%lf",&ps[i]);
        for (int i=0;i<n;i++)
        {
                for (int j=0;j<n;j++)
                {
                        if (i==j)
                        {
                                mat[i*n+j][i*n+j]=1;
                                continue;
                        }
                        Edge *ne1,*ne2;
                        for (ne1=V[i];ne1;ne1=ne1->next)
                                for (ne2=V[j];ne2;ne2=ne2->next)
                                        mat[ne1->np*n+ne2->np][i*n+j]=-1*(1-ps[i])*(1-ps[j])/deg[i]/deg[j];
                        Edge *ne;
                        for (ne=V[i];ne;ne=ne->next)
                                mat[ne->np*n+j][i*n+j]=-1*ps[j]*(1-ps[i])/deg[i];
                        for (ne=V[j];ne;ne=ne->next)
                                mat[i*n+ne->np][i*n+j]=-1*(1-ps[j])*ps[i]/deg[j];
                        mat[i*n+j][i*n+j]=1-ps[i]*ps[j];
                        mat[i*n+j][n*n]=0;
                }
        }
        mat[a*n+b][n*n]=1;
        int l=n*n;
        for (int i=0;i<l;i++)
        {
                int x=-1;
                for (int j=i;j<=l;j++)
                {
                        if (abs(mat[j][i])>eps)
                                x=j;
                }
                assert(x!=-1);
                if (x!=i)
                        for(int j=0;j<=l;j++)
                                swap(mat[i][j],mat[x][j]);
                for (int j=i+1;j<l;j++)
                {
                        real tmp=mat[j][i]/mat[i][i];
                        for (int k=i;k<=l;k++)
                        {
                                mat[j][k]-=mat[i][k]*tmp;
                        }
                }
        }
        for (int i=l-1;i>=0;i--)
        {
                real tmp=mat[i][n*n];
                for (int j=i+1;j<n*n;j++)
                        tmp-=res[j]*mat[i][j];
                res[i]=tmp/mat[i][i];
        }
        for (int i=0;i<n;i++)
                printf("%.6lf ",res[i*n+i]);
}
概率1

概率期望dp以及高消在很多时候都是可以转化的,而适当的转化会使思维难度大大降低。

//Miller Rabin
//HDU 2138
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long qword;
qword pow_mod(qword x,qword y,int mod)
{
        qword ret=1%mod;
        while (y)
        {
                if (y&1)ret=ret*x%mod;
                x=x*x%mod;
                y>>=1;
        }
        return ret;
}

bool MillerRabin(qword a,int n)
{
        int x=n-1,y=0;
        while ((x&1)==0)x>>=1,y++;
        a=pow_mod(a,x,n);
        int pe=a;
        for (int i=0;i<y;i++)
        {
                pe=a;
                a=a*a%n;
                if (a==1 && pe!=n-1 && pe!=1)return false;
        }
        return a==1?true:false;
}

int main()
{
    //    freopen("input.txt","r",stdin);
        int n;
        int x;
        int s[6]={2,3,5,7,17,61};
        while (~scanf("%d",&n))
        {
                int ans=0;

                for (int i=0;i<n;i++)
                {
                        scanf("%d",&x);
                        if (x==1)
                        {
                                continue;
                        }else if (x==2)
                        {
                                ans++;
                                continue;
                        }
                        bool flag=true;
                        for (int j=0;j<6;j++)
                        {
                                if (s[j]>=x)continue;
                                if (!MillerRabin(s[j],x))
                                {
                                        flag=false;
                                        break;
                                }
                        }
                        if (flag)
                        {
                                ans++;
                        }
                }
                printf("%d
",ans);
       
Miller Rabin

这种时候还理解什么,赶快背啊!

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
#define MAXN 110000
#define MAXM 210
#define BIG 1000000000000000LL
typedef long long qword;
int a[MAXN];
qword s[MAXN];
qword dp[2][MAXN];
struct point
{
        qword x,y;
};
qword area(point p1,point p2,point p3)
{
        return (p1.x-p2.x)*(p1.y-p3.y) - (p1.y-p2.y)*(p1.x-p3.x);
}
point q[MAXN];

int main()
{
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        int n,m;
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++)
        {
                scanf("%d",&a[i]);
                //if (!a[i])i--,n--;
        }
        for (int i=1;i<=n;i++)
                s[i]=s[i-1]+a[i];
        for (int i=0;i<2;i++)
                for (int j=0;j<=n;j++)
                        dp[i][j]=-BIG;
        int head,tail;
        point pt;
        dp[0][0]=0;
        for (int i=1;i<=m;i++)
        {
                head=0;
                tail=-1;
                for (int j=1;j<=n;j++)
                {
                        pt.x=s[j-1];
                        pt.y=-s[n]*s[j-1]+dp[(i&1)^1][j-1];
                        while (head<tail && area(q[tail-1],q[tail],pt)>=0)
                        {
                                if (area(q[tail-1],q[tail],pt)==0)
                                {
                                        cout<<"haha"<<endl;
                                }
                                tail--;
                        }
                        q[++tail]=pt;
                        while (head<tail && s[j]*q[head].x+q[head].y<=s[j]*q[head+1].x+q[head+1].y)
                                head++;
                        dp[i&1][j]=s[j]*q[head].x+q[head].y + s[n]*s[j]-s[j]*s[j];
        //                printf("%lld ",dp[i&1][j]);
                }
                dp[i&1][0]=-BIG;
        //        printf("
");
        }
        qword ans=0;
        for (int i=1;i<=n;i++)
                ans=max(ans,dp[m&1][i]);
        printf("%lld
",ans);
}
斜率优化
//POJ 1160
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 3100
#define MAXM 40
#define INF 0x3f3f3f3f
int w[MAXN][MAXN],w1[MAXN][MAXN];
int a[MAXN];
int dp[MAXM][MAXN];
pair<int,int> srange[MAXN];
int stack[MAXN];
int tops=-1;

int main()
{
        freopen("input.txt","r",stdin);
        int n,m;
        int x,y,z;
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++)
                scanf("%d",a+i);
        for (int i=1;i<=n;i++)
        {
                for (int j=i;j<=n;j++)
                {
                        if ((i+j)/2==(i+j-1)/2)
                                w[i][j]=w[i][j-1]+a[j]-a[(i+j)/2];
                        else
                                w[i][j]=w[i][j-1]+(a[(i+j)/2]-a[(i+j-1)/2])*(((i+j)/2-i) - (j-(i+j)/2))
                                        +a[j]-a[(i+j)/2];
                }
        }
        memset(dp,INF,sizeof(dp));
        dp[0][0]=0;
        srange[++tops]=make_pair(1,n);
        stack[tops]=0;
        for (int i=1;i<=m;i++)
        {
                while (~tops)
                {
                        for (int j=srange[tops].first;j<=srange[tops].second;j++)
                                dp[i][j]=dp[i-1][stack[tops]]+w[stack[tops]+1][j];
                        tops--;
                }
                for (int j=1;j<=n;j++)
                {
                        while (~tops && dp[i][j]+w[j+1][srange[tops].first]<dp[i][stack[tops]]+w[stack[tops]+1][srange[tops].first])
                                tops--;
                        if (~tops)
                        {
                                int l=srange[tops].first;
                                int r=srange[tops].second+1;
                                while (l+1<r)
                                {
                                        int mid=(l+r)>>1;
                                        if (dp[i][j]+w[j+1][mid]<dp[i][stack[tops]]+w[stack[tops]+1][mid])
                                                r=mid;
                                        else
                                                l=mid;
                                }
                                srange[tops].second=l;
                                if (r<=n)
                                {
                                        srange[++tops]=make_pair(r,n);
                                stack[tops]=j;
                                }
                        }else
                        {
                                srange[++tops]=make_pair(1,n);
                                stack[tops]=j;
                        }
                }
        }
        int ans=dp[m][n];
        printf("%d
",ans);
        return 0;
}
1D1D优化
//bzoj 1856
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MOD 20100403
#define MAXN 2001000
typedef long long qword;
qword fact[MAXN];
qword pow_mod(qword x,qword y)
{
        qword ret=1;
        while (y)
        {
                if (y&1)ret=ret*x%MOD;
                x=x*x%MOD;
                y>>=1;
        }
        return ret;
}
qword C(int x,int y)
{
        if (x<y)return 0;
        return fact[x]*pow_mod(fact[x-y],MOD-2)%MOD*pow_mod(fact[y],MOD-2)%MOD;
}

int main()
{
        //freopen("input.txt","r",stdin);
        int n,m;
        scanf("%d%d",&n,&m);
        fact[0]=1;
        for (int i=1;i<=n+m;i++)
                fact[i]=fact[i-1]*i%MOD;
        qword ans=C(n+m,n)-C(n+m,n+1);
        ans=(ans%MOD+MOD)%MOD;
        printf("%d
",(int)ans);
}
Catalan
Tarjan-缩点
Tarjan-边双&&非递归
Tarjan-点双
整体二分
//bzoj 3339
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<set>
using namespace std;
#define MAXN 210000
#define smid ((l+r)>>1)
int n,m;
int a[MAXN];
int tmp[MAXN],prv[MAXN];
const int big=200000;
struct qur_t
{
        int id,l,r,ans;
}qur[MAXN];
vector<qur_t> vec;
bool cmp_r(qur_t q1,qur_t q2)
{
        return q1.r<q2.r;
}
int res[MAXN];
void solve(int l,int r,vector<qur_t> &vec)
{
        if (l==r)
        {
                for (int i=0;i<vec.size();i++)
                        res[vec[i].id]=l;
                return ;
        }
        vector<qur_t> v1,v2;
        multiset<int> S;
        sort(vec.begin(),vec.end(),cmp_r);
        for (int i=l;i<=smid;i++)
                S.insert(tmp[i]);
        int cur=n;
        for (int i=vec.size()-1;i>=0;i--)
        {
                while (vec[i].r<cur)
                {
                        if (a[cur]<=smid && a[cur]>=l)
                        {
                                S.erase(S.find(cur));
                                S.insert(prv[cur]);
                        }
                        cur--;
                }
                if (*S.begin()<vec[i].l)
                        v1.push_back(vec[i]);
                else
                        v2.push_back(vec[i]);
        }
        solve(l,smid,v1);
        solve(smid+1,r,v2);
}

int main()
{
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        int x,y,z;
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++)
                scanf("%d",&a[i]);
        for (int i=1;i<=n;i++)
        {
                prv[i]=tmp[a[i]];
                tmp[a[i]]=i;
        }
        for (int i=1;i<=m;i++)
        {
                scanf("%d%d",&qur[i].l,&qur[i].r);
                qur[i].id=i;
        }
        vec.insert(vec.begin(),qur+1,qur+m+1);
        solve(0,big+1,vec);
        for (int i=1;i<=m;i++)
                printf("%d
",res[i]);

}
SBT && 动态凸包

 

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