两次考试

10.22

T1

异或支持一些律,把后面的移到前面就行了

 

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define rint register int
using namespace std;
const int N=100006;
inline void readint(int &x)
{
    x=0; char q=getchar();
    while(q<'0'||q>'9') q=getchar();
    while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
}

int n;
int f[N],g[N];

int main(){

    //freopen("T1.in","r",stdin);
    //freopen("T1.out","w",stdout);

    rint i,j;

    readint(n);
    for(i=0;i<n;++i) readint(f[i]);
    for(i=0;i<n;++i) readint(g[i]);
    int tt=0;
    for(i=0;i<n;++i)
    {
        tt=(tt^(f[i]^g[i]));
        printf("%d ",tt);
    }
}
T1

 

 

 

T2

对于只有1、2的情况

ans就是最底下一层最中间开始数到左右两边最近的连续的一段

推广到1~n

可以二分一个值,把比它小的设成1,大于等于的设成2,就可以O(n)求出来结果

是1,说明ans比二分的这个值小

否则,就大于等于

其实数据比较水,对中间三个排序,输出中位数就A了...

 

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define rint register int
using namespace std;
const int N=100006;
inline void readint(int &x)
{
    x=0; char q=getchar();
    while(q<'0'||q>'9') q=getchar();
    while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
}

int n;
int f[N],g[N];

int main(){

    //freopen("T1.in","r",stdin);
    //freopen("T1.out","w",stdout);

    rint i,j;

    readint(n);
    for(i=0;i<n;++i) readint(f[i]);
    for(i=0;i<n;++i) readint(g[i]);
    int tt=0;
    for(i=0;i<n;++i)
    {
        tt=(tt^(f[i]^g[i]));
        printf("%d ",tt);
    }
}
T2正解

 

 

 

T3

考试有思想,但是没打出来

先把T2的边在T1上进行线段覆盖

如果T1上有只覆盖1层的,就可以用它来满足覆盖它的那个边

都满足就YES,否则NO

 

#pragma GCC optimize("O3")
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define rint register int
using namespace std;
inline void read(int &x)
{
    x=0; char q=getchar();
    while(q<'0'||q>'9') q=getchar();
    while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
}
const int N=200006;
const int INF=1000000000;
int first[N],nt[N],ver[N],e;
inline void addbian(int u,int v)
{
    ver[e]=v;
    nt[e]=first[u];
    first[u]=e++;
}

int T;
int n;
int u[N],v[N];

int mn[N*5],sum[N*5],jiid[N*5],jiv[N*5];
int L,R,oo,vv,pos,id;
inline void add(int l,int r,int x)
{
    if(L<=l&&r<=R)
    {
        mn[x]+=vv;
        sum[x]+=(oo*(r-l+1));
        jiv[x]+=vv;
        jiid[x]+=oo;
        return ;
    }

    int mid=(l+r)>>1,ls=x<<1,rs=x<<1|1;

    if(jiid[x])
    {
        jiid[ls]+=jiid[x];
        jiid[rs]+=jiid[x];
        sum[ls]+=jiid[x]*(mid-l+1);
        sum[rs]+=jiid[x]*(r-mid);
        jiid[x]=0;
    }
    if(jiv[x])
    {
        jiv[ls]+=jiv[x];
        jiv[rs]+=jiv[x];
        mn[ls]+=jiv[x];
        mn[rs]+=jiv[x];
        jiv[x]=0;
    }

    if(L<=mid) add(l,mid,ls);
    if(mid<R) add(mid+1,r,rs);

    mn[x]=(mn[ls]<mn[rs]?mn[ls]:mn[rs]);
    sum[x]=sum[ls]+sum[rs];
}
inline void qq(int l,int r,int x)
{
    if(l==r)
    {
        if(mn[x]==1) mn[x]=INF,pos=l,id=sum[x];
        return ;
    }
    int mid=(l+r)>>1,ls=x<<1,rs=x<<1|1;
    if(jiid[x])
    {
        jiid[ls]+=jiid[x];
        jiid[rs]+=jiid[x];
        sum[ls]+=jiid[x]*(mid-l+1);
        sum[rs]+=jiid[x]*(r-mid);
        jiid[x]=0;
    }
    if(jiv[x])
    {
        jiv[ls]+=jiv[x];
        jiv[rs]+=jiv[x];
        mn[ls]+=jiv[x];
        mn[rs]+=jiv[x];
        jiv[x]=0;
    }

    if(mn[ls]==1) qq(l,mid,ls);
    else qq(mid+1,r,rs);

    mn[x]=(mn[ls]<mn[rs]?mn[ls]:mn[rs]);
    sum[x]=sum[ls]+sum[rs];
}

int fa[N],dep[N],size[N],son[N];
inline void dfs1(int x)
{
    size[x]=1;
    for(int i=first[x];i!=-1;i=nt[i])
    {
        if(ver[i]==fa[x])
            continue;
        fa[ver[i]]=x;
        dep[ver[i]]=dep[x]+1;
        dfs1(ver[i]);
        size[x]+=size[ver[i]];
        if(size[son[x]]<size[ver[i]])
            son[x]=ver[i];
    }
}
int top[N],zheng[N],timer;
inline void dfs2(int x,int tp)
{
    top[x]=tp; zheng[x]=++timer;
    if(son[x])
        dfs2(son[x],tp);
    for(int i=first[x];i!=-1;i=nt[i])
    {
        if(ver[i]==fa[x]||ver[i]==son[x])
            continue;
        dfs2(ver[i],ver[i]);
    }
}
inline void ADD(int x,int y)
{
    int fx=top[x],fy=top[y];
    while(fx!=fy)
    {
        if(dep[fx]<dep[fy])
        {
            x^=y; y^=x; x^=y;
            fx^=fy; fy^=fx; fx^=fy;
        }
        L=zheng[fx]; R=zheng[x];
        add(1,n,1);
        x=fa[fx];
        fx=top[x];
    }
    if(dep[x]>dep[y]) x^=y,y^=x,x^=y;
    if(x!=y) L=zheng[x]+1,R=zheng[y],add(1,n,1);
}

inline int work()
{
    mem(ver,0); mem(first,-1); mem(nt,0); e=0;
    mem(son,0); mem(size,0);
    timer=0;
    mem(mn,0); mem(sum,0); mem(jiv,0); mem(jiid,0);
    rint i,j; int tin1,tin2;
    for(i=1;i<n;++i)
    {
        read(tin1); read(tin2);
        addbian(tin1,tin2);
        addbian(tin2,tin1);
    }
    for(i=1;i<n;++i)
        read(u[i]), read(v[i]);
    fa[1]=-1; dep[1]=0;
    dfs1(1);
    dfs2(1,1);
    L=1; R=1; vv=INF; oo=0;
    add(1,n,1);
    for(i=1;i<n;++i)
        oo=i,vv=1,ADD(u[i],v[i]);
    for(i=1;i<n;++i)
    {
        id=0; pos=0;
        qq(1,n,1);
        if(!id) return 0;
        oo=-id; vv=-1;
        ADD(u[id],v[id]);
    }
    return 1;
}

int main(){
    
    //freopen("T3.in","r",stdin);

    //freopen("tree13.in","r",stdin);

    read(T);
    while(T--)
    {
        read(n);
        if(work())
            printf("YES\n");
        else
            printf("NO\n");
    }
}
T3

 

 

 

10.23

T1

有两种做法

(1) 

二分答案,用并查集维护,复杂度$O(n^2logn)$

当然,你需要韩门神的疯狂剪枝和超小常数...

(2)

对每一个星星和上下两个边界进行两两连边,边权是他们之间的距离

跑最小生成树(prim),再找从上边界到下边界的路径上的最小值/2即可

 

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <cmath>
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define dd double
#define rint register int
//#define dis(x3,y3,x4,y4) (sqrt((y3-y4)*(y3-y4)+(x3-x4)*(x3-x4)))
#define esp 0.0000001
using namespace std;
inline void read(int &x)
{
    x=0; char q=getchar();
    while(q<'0'||q>'9') q=getchar();
    while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
}
const int MAXK=10006;
int first[MAXK*3],nt[MAXK*3],ver[MAXK*3],e;
dd w[MAXK*3];
void addbian(int u,int v,dd _w)
{
    ver[e]=v;
    w[e]=_w;
    nt[e]=first[u];
    first[u]=e++;
}

int n,m,K;
int x[MAXK+100],y[MAXK+100];
dd mn[MAXK+100];
bool ff[MAXK+100];
int pr[MAXK+100];

inline dd dis(int f1,int f2)
{
    if( (f1==0&&f2==K+1)||(f1==K+1&&f2==0) ) return m;
    if(f1==0) return y[f2];
    if(f1==K+1) return m-y[f2];
    if(f2==0) return y[f1];
    if(f2==K+1) return m-y[f1];
    return sqrt((y[f1]-y[f2])*(y[f1]-y[f2])+(x[f1]-x[f2])*(x[f1]-x[f2]));
}

dd an[MAXK+100];
void dfs(int x)
{
    for(int i=first[x];i!=-1;i=nt[i])
    {
        if(an[ver[i]]>w[i])
            an[ver[i]]=w[i];
        dfs(ver[i]);
    }
}

dd work()
{
    rint i,j; int all=K+1;
    
    for(i=all+1;i>=0;--i) mn[i]=an[i]=0x7fffffff;
    mn[0]=0;
    int tt; dd vv;
    for(i=0;i<=all;++i)
    {
        tt=all+1;
        for(j=0;j<=all;++j)
            if(!ff[j]&&mn[tt]>mn[j])
                tt=j;
        ff[tt]=1;
        //printf("i=%d tt=%d\n",i,tt);
        for(j=0;j<=all;++j)
            if(!ff[j])
            {
                vv=dis(tt,j);
                //printf("j=%d vv=%lf\n",j,vv);
                if(mn[j]>vv)
                  mn[j]=vv,pr[j]=tt;
            }
    }
    for(i=1;i<=all;++i)
        addbian(pr[i],i,mn[i]);
    dfs(0);
    return an[all]/2.0;
}

int main(){
    
    freopen("T1.in","r",stdin);
    //freopen("T1.out","w",stdout);
    
    mem(first,-1);
    
    rint i,j;
    
    read(n); read(m); read(K);
    for(i=1;i<=K;++i) read(x[i]),read(y[i]);
    printf("%.8lf",work());
}
解1

 

 

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <cmath>
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define dd double
#define rint register int
//#define dis(x3,y3,x4,y4) (sqrt((y3-y4)*(y3-y4)+(x3-x4)*(x3-x4)))
#define esp 0.0000001
using namespace std;
inline void read(int &x)
{
    x=0; char q=getchar();
    while(q<'0'||q>'9') q=getchar();
    while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
}
inline void readll(ll &x)
{
    x=0; char q=getchar();
    while(q<'0'||q>'9') q=getchar();
    while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
}
const int MAXK=10006;
int first[MAXK*3],nt[MAXK*3],ver[MAXK*3],e;
ll w[MAXK*3];
void addbian(int u,int v,ll _w)
{
    ver[e]=v;
    w[e]=_w;
    nt[e]=first[u];
    first[u]=e++;
}

int n,m,K;
ll x[MAXK+100],y[MAXK+100];
ll mn[MAXK+100],ans;
bool ff[MAXK+100];
int pr[MAXK+100];

inline ll dis(int f1,int f2)
{
    if(f1>f2) f1^=f2,f2^=f1,f1^=f2;
    if(f1==K+1&&f2==K+2) return (ll)m*m;
    if(f2==K+1) return y[f1]*y[f1];
    if(f2==K+2) return ((ll)m-y[f1])*((ll)m-y[f1]);
    return (y[f1]-y[f2])*(y[f1]-y[f2])+(x[f1]-x[f2])*(x[f1]-x[f2]);
}

void dfs(int x,int fa,ll ww)
{
    if(x==K+2)
    {
        ans=ww;
        return ;
    }
    for(int i=first[x];i!=-1;i=nt[i])
    {
        if(ver[i]==fa)
            continue;
        dfs(ver[i],x,max(ww,w[i]));
    }
}

dd work()
{
    rint i,j; int all=K+2;
    
    mem(mn,0x7f);
    mn[K+1]=0;
    int tt; ll vv;
    for(i=1;i<=all;++i)
    {
        tt=0;
        for(j=1;j<=all;++j)
            if(!ff[j]&&mn[tt]>mn[j])
                tt=j;
        ff[tt]=1;
        if(pr[tt])
            addbian(pr[tt],tt,mn[tt]),
            addbian(tt,pr[tt],mn[tt]);
        for(j=1;j<=all;++j)
            if(!ff[j])
            {
                vv=dis(tt,j);
                if(mn[j]>vv)
                  mn[j]=vv,pr[j]=tt;
            }
    }
    dfs(K+1,-1,0);
    return sqrt(ans)/2.0;
}

int main(){
    
    //freopen("T1.in","r",stdin);
    //freopen("T1.out","w",stdout);
    
    //freopen("in.in","r",stdin);
    
    mem(first,-1);
    
    rint i,j;
    
    read(n); read(m); read(K);
    for(i=1;i<=K;++i) readll(x[i]),readll(y[i]);
    printf("%.8lf",work());
}
2

 

 

T2

首先你可以暴搜(虽然我暴搜也打挂了),有20分

然后你发现,题目其实是让求一个极长的上升序列,可以$O(n^2)$dp,有40分

然后你又发现可以有一个加calc的$O(nlog^2n)$的线段树优化

这个calc的写法其实跟以前 金坷垃、treap、楼房建设 差不多

一般是 维护三个域

ans、由于两个子区间不可加性的辅助转移的变量、记录状态防止超时的量

 

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <cmath>
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define dd double
#define rint register int
using namespace std;
inline void read(int &x)
{
    x=0; char q=getchar();
    while(q<'0'||q>'9') q=getchar();
    while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
}
const int N=200006;

struct son
{
    int pos,p,c;
    bool friend operator < (son a,son b)
    {
        return a.p<b.p;
    }
}ji[N];

int n,INF;

int an[N*4],mx[N*4],ban[N*4];
int cal(int hi,int l,int r,int x)
{
    if(hi>mx[x]) return INF;
    if(l==r) return an[x];
    int mid=(l+r)>>1;
    if(hi>mx[x<<1|1]) return cal(hi,l,mid,x<<1);
    else return min(ban[x<<1],cal(hi,mid+1,r,x<<1|1));
}
void change(int pos,int hh,int vv,int l,int r,int x)
{
    if(l==r)
    {
        an[x]=vv; mx[x]=hh;
        return ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid) change(pos,hh,vv,l,mid,x<<1);
    else change(pos,hh,vv,mid+1,r,x<<1|1);
    mx[x]=max(mx[x<<1],mx[x<<1|1]);
    an[x]=min(an[x<<1|1],ban[x<<1]=cal(mx[x<<1|1],l,mid,x<<1));
}
void qq(int L,int R,int &ans,int &hi,int l,int r,int x)
{
    //printf("L=%d R=%d ans=%d hi=%d l=%d r=%d x=%d\n",L,R,ans,hi,l,r,x);
    if(L>R) return ;
    if(L<=l&&r<=R)
    {
        ans=min(ans,cal(hi,l,r,x));
        hi=max(hi,mx[x]);
        return ;
    }
    int mid=(l+r)>>1;
    if(mid<R)
        qq(L,R,ans,hi,mid+1,r,x<<1|1);
    if(L<=mid)
        qq(L,R,ans,hi,l,mid,x<<1);
}

int f[N];

int work()
{
    rint i,j; int tt,hi;
    sort(ji+1,ji+1+n);
    mem(an,0x7f); mem(ban,0x7f); mem(&INF,0x7f);
    for(i=1;i<=n;++i)
    {
        //printf("i=%d\n",i);
        hi=0; tt=INF;
        qq(1,ji[i].pos-1,tt,hi,1,n,1);
        if(tt==INF) tt=0;
        f[ji[i].pos]=tt+ji[i].c;
        change(ji[i].pos,ji[i].p,f[ji[i].pos],1,n,1);
    }
    /*printf("\n");
    for(i=1;i<=n;++i)
        printf("%d ",f[i]);
    printf("\n");*/
    return f[n];
}

int main(){
    
    //freopen("T2.in","r",stdin);
    //freopen("T2.out","w",stdout);
    
    rint i,j;
    
    read(n);
    for(i=1;i<=n;++i) ji[i].pos=i,read(ji[i].p);
    for(i=1;i<=n;++i) read(ji[i].c);
    ++n; ji[n].pos=n; ji[n].c=0; ji[n].p=0x7fffffff;
    cout<<work();
}
T2

 

 

 

T3

可以把式子变成一个类似于斜率的式子,之后就转变成求一个下凸壳

用可持久化单调栈维护

可持久化?

其实就是一个回溯的过程

弹栈还要二分弹,暴力弹会被卡成$O(n^2)$

 

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <cmath>
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define dd double
#define rint register int
using namespace std;
inline void read(int &x)
{
    x=0; char q=getchar();
    while(q<'0'||q>'9') q=getchar();
    while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
}
const int N=500006;
int first[N*3],nt[N*3],ver[N*3],e;
void addbian(int u,int v)
{
    ver[e]=v;
    nt[e]=first[u];
    first[u]=e++;
}

int n;
int c[N],dep[N];
int zhan[N*2],he;
dd an[N];

inline dd cross(int q,int w)
{
    return (dd)(c[w]-c[q])/(dd)(dep[w]-dep[q]);
}

int er(int l,int r,int order)
{
    int mid,tt,ans=r;
    while(l<=r)
    {
        mid=(l+r)>>1;
        tt=(cross(zhan[mid],order)<cross(zhan[mid-1],order));
        if(tt) ans=mid-1,r=mid-1;
        else l=mid+1;
    }
    return ans;
}

void dfs(int x)
{
    int pr,prv;
    ++he;
    prv=zhan[he];
    zhan[he]=x;
    pr=he;
    for(int i=first[x];i!=-1;i=nt[i])
    {
        dep[ver[i]]=dep[x]+1;
        if(he>1)
            he=er(2,he,ver[i]);
        an[ver[i]]=-cross(zhan[he],ver[i]);
        dfs(ver[i]);
        he=pr;
    }
    zhan[he]=prv;
}

int main(){
    
    //freopen("T3.in","r",stdin);
    
    rint i,j;
    
    mem(first,-1);
    
    read(n);
    int tin;
    for(i=1;i<=n;++i) read(c[i]);
    for(i=2;i<=n;++i)
    {
        read(tin);
        addbian(tin,i);
    }
    dep[1]=1;
    dfs(1);
    for(i=2;i<=n;++i)
        printf("%.10lf\n",an[i]);
}
T3

 

posted @ 2017-10-24 06:26  A_LEAF  阅读(135)  评论(0编辑  收藏  举报