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

挺好玩的一场比赛。

链接

A

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

#include
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=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 \text{i步之后仍然没有结束的概率}\)。这个是一个等比数列。

#include
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

C

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

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

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

#include
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 > info;
    set st;
    inline void ins(int x){
        st.insert(x);
        set::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 :: 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

D

duliu ccz

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

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

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

#include
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)> 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))