51nod 算法马拉松35(A-D)

Posted weiyanpeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 算法马拉松35(A-D)相关的知识,希望对你有一定的参考价值。

挺好玩的一场比赛。

链接

A

打表,打到\(2e4\)左右会发现有一个长度\(104\)的循环节。

#include<bits/stdc++.h>
using namespace std;
int col[5010][5010];
int dx[4] = 1,0,-1,0,dy[4] = 0,1,0,-1;
long long n,tem=0;

int main()

    cin >> n;
    int x=0,y=0,d=0;
    while(tem<n)
        ++tem;
        x = x+dx[d], y = y+dy[d];
        if(!col[x+2500][y+2500])d++;
        else d--;
        d+=4;d%=4;
        col[x+2500][y+2500]^=1;
        if(tem>=15447 && (n-tem)%104==0)
            long long d2 = (n-tem)/104;
            cout << (long long)x - 2ll*d2 << " " << (long long)y - 2ll*d2 << endl;
            return 0;
        
    
    cout << x << " " << y << endl;

B

答案是\(\sum _i \texti步之后仍然没有结束的概率\)。这个是一个等比数列。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
inline int add(int a,int b)a+=b;return a>=mod?a-mod:a;
inline int sub(int a,int b)a-=b;return a<0?a+mod:a;
inline int mul(int a,int b)return 1ll*a*b%mod;
inline int qpow(int a,int b)int ret=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;
/* math */
const int N = 5e6+5;
int p[N],n,a,b,c;

int main()

    cin >> n ;
    cin >> p[1] >> a >> b >> c;
    for(int i=2;i<=n;i++)p[i] = add(c,add(mul(b,p[i-1]), mul(mul(p[i-1],p[i-1]),a)));
    for(int i=2;i<n;i++)p[n*2-i]=p[i];
    int p2 = 1, totp = 0;
    for(int i=1;i<2*n-1;i++)
        // cout << p[i] << " " ;
        totp = add(totp, mul(p2, sub(1,p[i])));
        p2 = mul(p2, sub(1,p[i]));
    
    int ans = totp;
    ans = mul(totp,qpow(sub(1,p2),mod-2));
    cout << ans << endl;

C

分析一下会发现一个条边有贡献当且仅当两端子树都有一个点被选择了。

相当于子树内的点是一种颜色,子树外是另外一种。

维护连续颜色段,启发式合并就行了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
inline int add(int a,int b)a+=b;return a>=mod?a-mod:a;
inline int sub(int a,int b)a-=b;return a<0?a+mod:a;
inline int mul(int a,int b)return 1ll*a*b%mod;
inline int qpow(int a,int b)int ret=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;
/* math */
int n;
const int N = 2e5+5;
int hed[N],to[N],nxt[N],cnt;
inline void adde(int u,int v)
    ++cnt;to[cnt]=v,nxt[cnt]=hed[u];hed[u]=cnt;

int id[N];
inline long long S(long long x)
    return x*(x+1)/2;

struct Node
    long long ret;
    map<int,pair<int,int> > info;
    set<int> st;
    inline void ins(int x)
        st.insert(x);
        set<int>::iterator t = st.find(x), lst = t, nxt = t;
        int l=0,r=n+1;
        if(t!=st.begin())l = *(--lst);
        if(x!=*st.rbegin()) r = *(++nxt);
        ret -= S(r-l-1);
        int lft = x,rgt = x;
        if(l&&l==x-1)
            lft = info[l].first;
            ret-=S(l-lft+1);
        
        if(r!=n+1&&r==x+1)
            rgt = info[r].second;
            ret-=S(rgt-r+1);
        
        info[lft].second = rgt,info[rgt].first = lft;
        ret += S(rgt-lft+1);
        ret += S(r-1-x) + S(x-1-l);
    
;
Node nd[N];
inline void mrg(Node &a,Node &b)
    set<int> :: iterator t = b.st.begin();
    for(;t!=b.st.end();++t)
        a.ins(*t);
    

int sz[N];
long long ans = 0;
inline void dfs(int x,int pre)
    id[x] = x;
    nd[x].ret = S(n);
    nd[x].ins(x);
    sz[x] = 1;
    for(int i=hed[x];i;i=nxt[i])
        int v = to[i];if(v==pre)continue;
        dfs(v,x);
        int ths = id[x], nxt = id[v];
        if(sz[x] < sz[v])
            swap(ths,nxt);
        
        mrg(nd[ths],nd[nxt]);
        id[x] = ths;
        sz[x] += sz[v];
    
    if(pre)ans += S(n) - nd[id[x]].ret;


int main()

    cin >> n;
    for(int i=1;i<n;i++)
        int u,v;scanf("%d%d",&u,&v);
        adde(u,v),adde(v,u);
    
    dfs(1,0);
    ans*=2;ans%=mod;
    int ss = S(n)%mod;
    cout << mul(ans, qpow(ss,mod-2)) << endl;

D

duliu ccz

把线段按照斜率 $>0 / <0 $ 分组。

先拆成四组询问,全部包含的线可以轻松扫描线。现在分别考虑与纵轴相交的和与y轴相交的。因为线段不交,这些点都在一段区间。拆式子用平衡树维护就行了。

然后写题时间 \(8:00 \to 15:00\)我才不会告诉你我炸int调了3h

#include<bits/stdc++.h>
using namespace std;
typedef double db;
const int N = 4e5+5;
int n,m;
namespace sgt
    #define lowbit(x) ((x)&(-x))
    db tag[2000002];int cnt,rt;
    inline void ins(int x,db s)
        for(;x<=2000000;x+=lowbit(x))
            tag[x]+=s;
        
    
    inline db qry(int x)
        db ans = 0;
        while(x)
            ans+=tag[x];
            x-=lowbit(x);
        return ans;
    
    inline void clr()
        for(int i=1;i<=2000000;i++)tag[i]=0;
    

db sqr(db a)
    return a*a;

struct Line
    int x1,y1,x2,y2;
    bool operator < (const Line b)const
        return (y2-y1)/(x2-x1)<(b.y2-b.y1)/(b.x2-b.x1);
    
    db cal(int id)return (db)(y2-y1)*(db)(id-x1)/(db)(x2-x1) + (db)y1;
    db Sin()return (db)sqrt((db)sqr(y2-y1)+sqr(x2-x1))/(db)(x2-x1);
    db len()return (db)sqrt((db)sqr(y2-y1)+sqr(x2-x1));
l[N],l2[N];

int D = 0;
namespace Bt
    int curx;
    struct splaynode
        int ch[2],fa;db x,sx,x2,sx2;
    t[N];
    int null=0,root;
    inline bool son(int x)return t[t[x].fa].ch[1]==x;
    inline bool isroot(int x)return t[t[x].fa].ch[1]!=x&&t[t[x].fa].ch[0]!=x;
    inline void pushup(int x)
        t[x].sx=t[x].x+t[t[x].ch[0]].sx+t[t[x].ch[1]].sx;
        t[x].sx2=t[x].x2+t[t[x].ch[0]].sx2+t[t[x].ch[1]].sx2;
    
    inline void rotate(int x)
        int f=t[x].fa,gf=t[t[x].fa].fa;
        bool a=son(x),b=son(x)^1;
        if(!isroot(f))t[gf].ch[son(f)]=x;
        t[x].fa=gf;
        t[f].ch[a]=t[x].ch[b];t[t[x].ch[b]].fa=f;
        t[x].ch[b]=f;t[f].fa=x;
        pushup(f);pushup(x);//"pushup
    inline void dfs(int x)
        if(!x)return ;
        dfs(t[x].ch[0]);
        cout <<'[' <<  x  << " " << l[x].cal(curx) << ']'<< " ,";
        dfs(t[x].ch[1]);
    
    inline void print()
        dfs(root);puts("");
    
    inline void splay(int x)
        while(!isroot(x))
            int f=t[x].fa;
            if(!isroot(f))
                if(son(f)^son(x))rotate(x);
                else rotate(f);
            
            rotate(x);
        
        root=x;
    
    inline void splay2(int x)
        while(t[x].fa!=root)
            int f=t[x].fa;
            if(t[f].fa!=root)
                if(son(f)^son(x))rotate(x);
                else rotate(f);
            
            rotate(x);
        
    
    bool comp(int a,int b)
        return l[a].cal(curx)<l[b].cal(curx);
    
    bool cmp2(int a,int b)
        int d = curx - l[a].x1;
        int dy = l[a].y2-l[a].y1;
        int dx = l[a].x2-l[a].x1;
        int dt = b-l[a].y1;
        // cout << l[a].x1 << " " << l[a].x2 << " " << l[a].y1 << " " << l[a].y2 << " " << curx << ":" << b << "|||";
        // cout << d*dy << " " << dt*dx << endl;
        if(!D)return 1ll*d*dy<=1ll*dt*dx;
        else return 1ll*d*dy<1ll*dt*dx;
    
    
    inline void del(int x)
        // cout << "Delete" << " " << x << endl;
        splay(x);
        if(!t[x].ch[0])root=t[x].ch[1],t[root].fa=0;return;
        if(!t[x].ch[1])root=t[x].ch[0],t[root].fa=0;return;
        int lft = t[x].ch[0];while(t[lft].ch[1])lft = t[lft].ch[1];
        int nxt = t[x].ch[1];while(t[nxt].ch[0])nxt = t[nxt].ch[0];
        splay(lft);
        splay2(nxt);
        t[nxt].ch[0]=null;
        pushup(nxt),pushup(lft);
        // print();
    
    inline int query(int x,int yline)
        int id = root,ans = -1;
        while(id)
            bool side = cmp2(id,yline);
            if(side)ans = id;
            id = t[id].ch[side];
        
        return ans;
    
    
    inline void ins(int x)
        if(!root)root = x;else
            int lst = query(root,l[x].y1);
            if(lst==-1)t[x].ch[1]=root,t[root].fa=x;root=x,pushup(x);
            else
                splay(lst);
                int nxt = t[root].ch[1];
                if(!nxt)t[root].ch[1]=x,t[x].fa = root,pushup(root);
                else
                    while(t[nxt].ch[0])nxt=t[nxt].ch[0];
                    splay2(nxt);
                    t[nxt].ch[0]=x;t[x].fa=nxt;
                    pushup(nxt),pushup(root);
                
            
        
        // cout << "ins" << x << endl;
        // print();
    

    void clr()
        for(int i=1;i<N;i++)t[i].ch[0]=t[i].ch[1]=t[i].fa=0,t[i].x=t[i].sx=t[i].x2=t[i].sx2=0;
        root=0;curx=-1e9;
    


struct query
    int x,y,id,d;
    query(int x=0,int y=0,int id=0,int d=0):x(x),y(y),id(id),d(d)
    bool operator < (const query b)constreturn x<b.x;
q[N<<3];
struct op
    int x,y,id,d;
    op(int x=0,int y=0,int id=0,int d=0):x(x),y(y),id(id),d(d)
    bool operator < (const op b)constreturn x==b.x?(d<b.d):x<b.x;
o[N<<2];int tcnt;


inline void perform(int x)
    // cout << "per" << " " << o[x].id << " " << o[x].d << endl;
    Bt::curx = o[x].x;
    int id = o[x].id;
    // cout << id << " " << l[id].Cos() << endl;

    if(o[x].d==1)
        Bt::t[id].x = l[id].Sin();
        Bt::t[id].x2 = l[id].x1*l[id].Sin();
        Bt::pushup(id);
        Bt::ins(id);
    else
        Bt::del(id);
        if(!D)sgt::ins(l[id].y2,l[id].len());
    
    // Bt::print();
    // puts("fin");

db ret[N];
inline void Query(int x)
    Bt::curx = q[x].x;
    // cout << "q" << D << ":;" << q[x].x << " " << q[x].y << "," << q[x].d << endl;
    // Bt::print();
    db ans1 = 0;
    if(!D)ans1 += sgt::qry(q[x].y);
    
        // cout << ":" << ans1 << "..";
    int id1 = Bt::query(Bt::root,q[x].y);
    // cout << id1 << " " << ".." << endl;
    using namespace Bt;
    if(id1!=-1)
        Bt::splay(id1);
        int nxt = t[id1].ch[1];
        t[id1].ch[1]=0;pushup(id1);
        ans1+=(db)t[id1].sx*curx-t[id1].sx2;
        t[id1].ch[1]=nxt;pushup(id1);
    
    // printf("%.6lf\n",ans1);
    ret[q[x].id] += (db)q[x].d*ans1;
    // Bt::print();
    // puts("--");

int _A[N],_B[N],_C[N],_D[N];

db tot = 0;
int main()

    cin >> n;
    for(int i=1;i<=n;i++)
        scanf("%d%d%d%d",&l2[i].x1,&l2[i].y1,&l2[i].x2,&l2[i].y2);
        if(l2[i].x1>l2[i].x2)
            swap(l2[i].x1,l2[i].x2), swap(l2[i].y1,l2[i].y2);
        
        tot += sqrt((db)sqr(l2[i].x1-l2[i].x2)+(db)sqr(l2[i].y1-l2[i].y2));
    
    sort(l2+1,l2+n+1);
    cin >> m;
//-----------------------------
    D=0;
    sgt::clr();Bt::clr();Bt::curx=-1e9;
    for(int i=1;i<=m;i++)
        int a,b,c,d;
        scanf("%d%d%d%d",&a,&b,&c,&d);
        _A[i]=a,_B[i]=b,_C[i]=c,_D[i]=d;
        q[i*4-3] = query(a,b,i,1);
        q[i*4-2] = query(c,d,i,1);
        q[i*4-1] = query(a,d,i,-1);
        q[i*4-0] = query(c,b,i,-1);
    
    // cout << "???" << endl;
    tcnt=0;for(int i=1;i<=n;i++)
        l[i]=l2[i];
        if(l2[i].y1 <= l2[i].y2)
            o[++tcnt] = op(l[i].x1,l[i].y1,i,1);
            o[++tcnt] = op(l[i].x2,l[i].y2,i,-1);
        
    
    sort(q+1,q+m*4+1);sort(o+1,o+tcnt+1);
    int tar = 1;
    for(int d=1;d<=m*4;d++)
        while(tar<=tcnt && o[tar].x <= q[d].x)
            perform(tar);tar++;
        Query(d);
    
    /////
    D=1;
    sgt::clr();Bt::clr();Bt::curx=-1e9;
    for(int i=1;i<=m*4;i++)swap(q[i].x,q[i].y);
    tcnt=0;for(int i=1;i<=n;i++)
        l[i]=l2[i];
        swap(l[i].x1,l[i].y1);
        swap(l[i].x2,l[i].y2);
        if(l2[i].y1 <= l2[i].y2)
            o[++tcnt] = op(l[i].x1,l[i].y1,i,1);
            o[++tcnt] = op(l[i].x2,l[i].y2,i,-1);
        
    
    sort(q+1,q+m*4+1);sort(o+1,o+tcnt+1);
    tar = 1;
    for(int d=1;d<=m*4;d++)
        while(tar<=tcnt && o[tar].x <= q[d].x)
            perform(tar);tar++;
        Query(d);
    
//----------------------------------------
    D=0;
    sgt::clr();Bt::clr();Bt::curx=-1e9;
    for(int i=1;i<=m;i++)
        int a=_A[i],b=_B[i],c=_C[i],d=_D[i];
        q[i*4-3] = query(-a,b,i,-1);
        q[i*4-2] = query(-c,d,i,-1);
        q[i*4-1] = query(-a,d,i,1);
        q[i*4-0] = query(-c,b,i,1);
    
    tcnt=0;for(int i=1;i<=n;i++)
        l[i]=l2[i];
        if(l2[i].y1>l2[i].y2)
            l[i].x1=-l[i].x1,l[i].x2=-l[i].x2;
            swap(l[i].x1,l[i].x2),swap(l[i].y1,l[i].y2);
            o[++tcnt] = op(l[i].x1,l[i].y1,i,1);
            o[++tcnt] = op(l[i].x2,l[i].y2,i,-1);
        
    
    sort(q+1,q+m*4+1);sort(o+1,o+tcnt+1);
    tar = 1;
    for(int d=1;d<=m*4;d++)
        while(tar<=tcnt && o[tar].x <= q[d].x)
            perform(tar);tar++;
        Query(d);
    
    /* CUTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT */
    D=1;
    sgt::clr();Bt::clr();Bt::curx=-1e9;
    for(int i=1;i<=m*4;i++)swap(q[i].x,q[i].y);
    tcnt=0;for(int i=1;i<=n;i++)
        l[i]=l2[i];
        if(l2[i].y1 > l2[i].y2)
            l[i].x1=-l[i].x1,l[i].x2=-l[i].x2;
            swap(l[i].x1,l[i].x2),swap(l[i].y1,l[i].y2);
            swap(l[i].x1,l[i].y1);swap(l[i].x2,l[i].y2);
            o[++tcnt] = op(l[i].x1,l[i].y1,i,1);
            o[++tcnt] = op(l[i].x2,l[i].y2,i,-1);
        
    
    sort(q+1,q+m*4+1);sort(o+1,o+tcnt+1);
    tar = 1;
    for(int d=1;d<=m*4;d++)
        while(tar<=tcnt && o[tar].x <= q[d].x)
            perform(tar);tar++;
        Query(d);
    
//-----------------------------
    for(int i=1;i<=m;i++)
        printf("%.8lf\n",1e-15+ret[i]/tot);
    

以上是关于51nod 算法马拉松35(A-D)的主要内容,如果未能解决你的问题,请参考以下文章

51nod算法马拉松15

51nod算法马拉松28-a

51nod算法马拉松14

51nod算法马拉松28-c

随便玩玩系列之一:SPOJ-RNG+51nod 算法马拉松17F+51nod 1034 骨牌覆盖v3

51nod 算法马拉松17 解题报告