陈题记录

5 Solved.

NOI2014

起床困难综合症

老早做的,因为位运算对于每一位都是独立的,那么先执行所有操作再计算最大效果即可.

魔法森林

我们把边权先按a排序(递增),这保证了对于前面的a总是最优的.每次加边,如果成环删去环上最大的边.实现技巧就是将边也看成点处理,这样就可以拿来一起link-cut了.

#include <cstdio>
#include <algorithm>
#define rg register
template<class T> inline void swp(T& a,T& b){ T x=a; a=b,b=x; }
inline void tensen(int& a,int b){ if(b<a) a=b; }
struct edge{ int f,t,a,b; } e[100010];
struct data{ int v,e; } empty=(data){0,0};
struct node;
node *null_node;
int n,m;
struct node{
    node *ch[2],*fa;
    data  hr,mx;
    node *top;
    bool  revf;
    inline void rev(){
        revf^=1; swp(ch[0],ch[1]);
    }
    inline void pd (){
        if(revf){
            ch[0]->rev(),ch[1]->rev(),revf=0;
        }
    }
    inline void pu (){
        if(ch[0]->mx.v > ch[1]->mx.v) mx=ch[0]->mx; else mx=ch[1]->mx;
        if(hr.v > mx.v) mx=hr;
    }
    inline void rot(rg bool f){
        node *fx=fa;
        top=fx->top; fx->pd(), pd();
        (fa=fx->fa)->ch[fx->fa->ch[1]==fx]=this;
        (fx->ch[f]=ch[!f])->fa=fx;
        (ch[!f]=fx)->fa=this;
        fx->pu();
    }
    inline void spl(rg bool f=0){
        node *fx=fa;
        for(pd();fx!=null_node;fx=fa){
            if(fx->fa==null_node) rot(fx->ch[1]==this); else
            if((fx->fa->ch[1]==fx)==(f=(fx->ch[1]==this))){
                fx->rot(f),rot(f);
            }else rot(f),rot(!f);
        }
    }
    inline void exp(node *p=null_node){
        spl(); if(ch[1]!=null_node) ch[1]->top=this,ch[1]->fa=null_node;
        (ch[1]=p)->fa=this; pu();
    }
} tr[150030];
#define init1 null_node=tr;
#define beg init1
inline node*acc(node *x){
    for(x->exp();x->top;x=x->top) x->top->exp(x);
    return x;
}
inline void lnk(node *x,node *y){ (x=acc(x))->rev(); x->top=y; }
inline void cut(node *x,node *y){ x->exp(),y->exp(); if(x->top==y) x->top=NULL; if(y->top==x) y->top=NULL; }
struct rslt{ bool h; data r; };
inline rslt chk(node *x,node *y){
    acc(x); data res=empty; node *A = acc(y);
    if(A->ch[1]!=null_node) if(A->ch[1]->mx.v > res.v) res=A->ch[1]->mx;
    node *B = acc(x); if(A!=B) return (rslt){0,res}; 
    if(B->ch[1]!=null_node) if(B->ch[1]->mx.v > res.v) res=B->ch[1]->mx;
    if(A->hr.v > res.v) return (rslt){1,A->hr}; else return (rslt){1,res};
}
inline bool cmp(const edge& a,const edge& b){ return a.a < b.a; }
inline void wrk(){
    beg
    int x,y;
    scanf("%d%d",&n,&m);
    for(int i=1,a,b;i<=m;++i){
        scanf("%d%d%d%d",&n,&m,&a,&b);
        e[i]=(edge){x,y,a,b};
        if(x==y) --i,--m;
    }   std::sort(e+1,e+m+1,cmp);
    for(int i=0;i<=n;++i) tr[i]=(node){{null_node,null_node},null_node};
    int ans=1<<30,t; node *cur, *P=tr, *E=tr+n; rslt R;
    for(int i=1;i<=m;++i){
        if(e[i].a >= ans) break;
        *(cur=E+i)=(node){{null_node,null_node},null_node,(data){e[i].b,i}};
        R=chk(P+e[i].f,P+e[i].t); if(R.h){if(R.r.v > e[i].b){
            t=R.r.e;
            cut(P+e[t].f,E+t),cut(P+e[t].t,E+t);
            lnk(P+e[i].f,cur),lnk(P+e[i].t,cur);
        }}else
            lnk(P+e[i].f,cur),lnk(P+e[i].t,cur);
        if(e[i].a!=e[i+1].a) if((R=chk(P+1,P+n)).h) tensen(ans,R.r.v+e[i].a);
    }
    if(ans<(1<<30)) printf("%d\n",ans); else printf("-1\n");
}
int main(){
    wrk();
    return 0;
}

动物园

可以推广到回文树上,见CC PALPROB.

#include <cstdio>
#include <cstring>
#define maxn 1000005
char s[maxn];
int fail[maxn],hfail[maxn],dep[maxn];
int main(){
    //can be applied to palindrome trees CC http://www.codechef.com/problems/PALPROB
    int a;
    scanf("%d",&a);
    while(~scanf("%s",s+1)){
        int len=strlen(s+1);
        dep[1]=1;
        int ans=1;
        for(int i=2;i<=len;++i){
            int j=fail[i-1];
            while(s[j+1]!=s[i] && j) j=fail[j];
            if(s[j+1]==s[i]) fail[i]=j+1; else fail[i]=0;
            dep[i]=dep[fail[i]]+1;
            j=hfail[i-1];
            while((s[j+1]!=s[i] || (((j+1)<<1) > i)) && j) j=fail[j];
            if(s[j+1]==s[i]) hfail[i]=j+1; else hfail[i]=0;
            ans=(long long)ans*(dep[hfail[i]]+1)%1000000007;
        }
        printf("%d\n",ans);
    }
    return 0;
}

随机数生成器

都是些什么鬼题目...

大暴力,每次\(\overline{O\left(1\right)}\)判断能否加进一个点,如果要加入\(\overline{O\left(n\right)}\)修改.总时间复杂度\(\overline{O\left(nm+n^2\right)}\).

#include <cstdio>
#include <algorithm>
int per[25000010],rep[25000010],l[5010],r[5010];
int x,a,b,c,d;
int n,m,q;
#define rnd (x=(((long long)a*x+b)*x+c)%d)
inline void ge(){
    scanf("%d%d%d%d%d",&x,&a,&b,&c,&d);
    scanf("%d%d%d",&n,&m,&q);
    int mn=n*m;
    for(int i=1;i<=mn;++i) per[i]=i;
    for(int i=1;i<=mn;++i){
        int r=rnd%i+1;
        if(r==i) continue;
        std::swap(per[i],per[r]);
    }
    for(int i=0,a,b;i<q;++i) scanf("%d%d",&a,&b),std::swap(per[a],per[b]);
    for(int i=1;i<=mn;++i) rep[per[i]]=i-1;
}
int main(){
    ge();
    int cnt=0,mn=m*n;
    for(int i=0;i<=m;++i) r[i]=n+1;
    for(int i=1;i<=mn;++i){
        if(cnt==n+m-1) break;
        int x=rep[i]/m+1,y=rep[i]%m+1;
        if(l[y]<=x && x<=r[y]){
            printf("%d ",i);
            ++cnt;
            for(int j=y-1;j && r[j]>x;--j) r[j]=x;
            for(int j=y+1;j<=m && l[j]<x;++j) l[j]=x;
        }
    }
    return 0;
}

购票

由于凸包维护时求斜率的double值函数打成int值函数而调了好长时间...

第一次写点分治,第一次写斜率优化DP.(我好弱啊...)其实是对着prwang代码写的..

感觉点分治写法好巧妙啊...由于这题是在链上推公式所以不需要虚点..

题解感觉要以后写了..这题我只是A掉了而已..

WC 2013

糖果公园

据说是树上带修改莫队,事实上是树上带修改莫队.

第一次写,感觉这个挺神奇的..

树上可以用缩减的DFS序维护(出入节点counter).

转载于:https://www.cnblogs.com/dolhea/p/5040587.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值