2017.7.22模拟赛被虐记录

感觉自己要完
成功被虐了两倍分。。
其实故事是这样的
看了第二题 发现是个SB树分
然后就没有然后了
突然Manchery说自己的代码会被卡常 然后我拿了大样例 没开优化跑了0.8s 时限2s 感觉很稳啊
看了第一题 完全没思路 看了看大样例 我日 SB题。。。 但是要特判几个hack点。。。
第三题 弃疗 暴力都不会。。。
然后。。。本机跑0.8s的我在评测机上2s TLE…
然而本机比我慢的Manchery就就就轻轻松松跑过去了
日 EXM?什么破机子 被卡常了
map真TM的慢。。早知道就不图方便自己打个数组记录

第一题 特判成功没考虑重复情况 成功gg

然后因为蜜汁数据打包问题。。。。
200 -> 70
EXM?200分rank2啊
感觉自己好弱啊QaQ

T1:找规律

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<map>
using namespace std;
#define Com complex<double>
const
    double pi=acos(-1);
char c;
#define ll long long
inline void read(ll &a)
{
    a=0;do c=getchar();while(c<'0'||c>'9');
    while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
}
ll a[100001];
ll P[100001];
const   int MAXN=2233333;
int Tot,prime[MAXN+1];
bool ck[MAXN+1];
bool Has[MAXN+1];
int main()
{
    for(int i=2;i<=MAXN;i++)
    {
        if(!ck[i])prime[++Tot]=i;
        for(int j=1,k=2*i;j<=Tot&&k<=MAXN;k=prime[++j]*i)
        {
            ck[k]=true;
            if(i%prime[j]==0)break;

        }
    }
    ll n,x;
    read(n),read(x);
    for(int i=1;i<=n;i++)read(a[i]),Has[a[i]>MAXN?0:a[i]]=true;

    sort(a+1,a+1+n);
    n=unique(a+1,a+1+n)-a-1;
    if(x==2){return puts("0"),0;}
    if(a[1]==1){return puts("1"),0;}
    if(a[1]!=2){return puts("-1"),0;}
    if(x==3){return puts("1"),0;}
    if(a[2]!=3){return puts("-1"),0;}
    if(n==1){return puts("-1"),0;}

    if(prime[n+1]<x){return puts("-1"),0;}

    int tot=0;
    for(int i=1;prime[i]<x;i++)
    {
        if(!Has[prime[i]]){return puts("-1"),0;}
        tot++;
    }
    cout<<tot<<endl;
    return 0;
}

T2:
Sol1: O(nlogn) 可持久化线段树加堆
Sol2: O(nlog2n) 点分树+超级钢琴
Sol3: O(nlog2n) 点分树+二分答案+Two Pointer累加

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<map>
using namespace std;
#define Com complex<double>
const
    double pi=acos(-1);
char c;
inline void read(int&a)
{
    a=0;do c=getchar();while(c<'0'||c>'9');
    while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
}
struct Chain
{
    int u,len;  
    Chain*next;
}*Head[100001];

inline void Add(int u,int v,int len)
{
    Chain*tp=new Chain;
    tp->u=v;
    tp->len=len;
    tp->next=Head[u];
    Head[u]=tp;
}

int All[5000001],Cur;
int SonBG[50001],SonED[50001],SubBG[50001],SubED[50001];

int Size[50001];
bool done[50001];
void GetSize(int u,int f)
{
    Size[u]=1;
    for(Chain*tp=Head[u];tp;tp=tp->next)
        if(tp->u^f&&!done[tp->u])GetSize(tp->u,u),Size[u]+=Size[tp->u];
}

int Rt,MX[50001],SUM;
void GetRoot(int u,int f)
{
    MX[u]=SUM-Size[u];
    for(Chain*tp=Head[u];tp;tp=tp->next)
        if(tp->u^f&&!done[tp->u])
            GetRoot(tp->u,u),MX[u]=max(MX[u],Size[tp->u]);
    if(MX[Rt]>MX[u])Rt=u;
}
int Cache[50001],tot;
bool Vis[50001];
int M;
void DFS(int u,int f,int Len)
{
    Cache[++tot]=Len,M=max(M,Len);
    for(Chain*tp=Head[u];tp;tp=tp->next)
    if(tp->u^f&&!done[tp->u])
        DFS(tp->u,u,Len+tp->len);
}
int Sont;
int F[200001],U[200001];
void Div(int u)
{

    done[u]=true;
    int t=Cur+1;
    for(Chain*tp=Head[u];tp;tp=tp->next)
    if(!done[tp->u])
    {
        tot=0;
        DFS(tp->u,u,tp->len);
        ++Sont;
        F[Sont]=u;
        U[Sont]=tp->u;
        SonBG[Sont]=1+Cur;
        for(int i=1;i<=tot;i++)
            All[++Cur]=Cache[i];
        SonED[Sont]=Cur;
        sort(All+SonBG[Sont],All+SonED[Sont]+1);
    }
    SubBG[u]=Cur+1;
    int MX=Cur;
    for(int i=t;i<=MX;i++)
        All[++Cur]=All[i];
    All[++Cur]=0;
    SubED[u]=Cur;

    sort(All+SubBG[u],All+SubED[u]+1);
    for(Chain*tp=Head[u];tp;tp=tp->next)
    if(!done[tp->u])
    {
        GetSize(tp->u,u);
        SUM=Size[tp->u];
        Rt=0;
        GetRoot(tp->u,u);
        Div(Rt);
    }
}


int n,m;
bool Query(int LEN)
{
    int Cnt=0;
    for(int i=1;i<=n;i++)
    {
        int *Data=All+SubBG[i]-1;
        int Y=SubED[i]-SubBG[i]+1,MAX=Y,X=Y-1;
        if(X<1||Data[X]+Data[Y]<LEN)continue;
        while(X>1&&Data[X-1]+Data[Y]>=LEN)X--;  
        while(X<Y)
        {
            while(X<Y&&Data[X]+Data[Y]<LEN)X++;
            Cnt+=Y-X;
            Y--;
        }

    }
    if(Cnt<m)return false;
    for(int i=1;i<=Sont;i++)
    {
        int *Data=All+SonBG[i]-1;
        int Y=SonED[i]-SonBG[i]+1,MAX=Y,X=Y-1;
        if(X<1||Data[X]+Data[Y]<LEN)continue;
        while(X>1&&Data[X-1]+Data[Y]>=LEN)X--;
        while(X<Y)
        {
            while(X<Y&&Data[X]+Data[Y]<LEN)X++;
            Cnt-=Y-X;
            Y--;
            if(Cnt<m)return false;
        }
    }
    return Cnt>=m?true:false;

}

//map<int,int>Val;
inline bool cmp(int a,int b){return abs(a)>abs(b);}
int Val[1000001],P;
void COUT(int LEN)
{
    for(int i=1;i<=n;i++)
    {
        int *Data=All+SubBG[i]-1;
        int Y=SubED[i]-SubBG[i]+1,MAX=Y,X=Y-1;
        if(X<1||Data[X]+Data[Y]<LEN)continue;
        while(X>1&&Data[X-1]+Data[Y]>=LEN)X--;

        while(X<Y)
        {
            while(X<Y&&Data[X]+Data[Y]<LEN)X++;
            for(int t=Y-1;t>=X;t--)
                Val[++P]=Data[Y]+Data[t];
            //Cnt+=Y-X;
            Y--;
        }

    }

    for(int i=1;i<=Sont;i++)
    {
        int *Data=All+SonBG[i]-1;
        int Y=SonED[i]-SonBG[i]+1,MAX=Y,X=Y-1;
        if(X<1||Data[X]+Data[Y]<LEN)continue;
        while(X>1&&Data[X-1]+Data[Y]>=LEN)X--;
        while(X<Y)
        {
            while(X<Y&&Data[X]+Data[Y]<LEN)X++;
            for(int t=Y-1;t>=X;t--)
                Val[++P]=-(Data[Y]+Data[t]);
            Y--;
        }
    }
    sort(Val+1,Val+1+P,cmp);
    int t=0,k;
    for(int i=1;i<=P;i=t+1)
    {
        t=i,k=Val[i];
        while(t<P&&(!cmp(Val[t],Val[t+1]))&&!cmp(Val[t+1],Val[t]))
            k+=Val[++t];
        int p=k/abs(Val[i]),o=abs(Val[i]);
        for(int i=1;i<=p;i++)
            printf("%d\n",o);
    }
}

int main()
{

    read(n),read(m);
    for(int i=2;i<=n;i++)
    {
        int a,b,c;
        read(a),read(b),read(c);
        Add(a,b,c),Add(b,a,c);
    }
    GetSize(1,1);
    SUM=n;
    MX[Rt=0]=n*2;
    //SonBG[Rt]=1;
    GetRoot(1,1);
    Div(Rt);
    int L=1,R=M*2,Mid;
    while(L<R)
    {
        Mid=L+R>>1;
        Mid++;
        if(Query(Mid))L=Mid;
        else R=Mid-1;
    }
    //return 0;
    COUT(L);
    return 0;
}

T3:考虑数字0与1出现情况
0只能由1得出
1可以由0或1得出
压缩01的状态 发现若最终态合法则可行

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;

char c;
inline void read(int&a)
{
    a=0;do c=getchar();while(c<'0'||c>'9');
    while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
}

int a[100021],n;
bool ck()
{
    int i;
    while(n>1)
    {
        if(!a[i])a[1]=2;
        if(a[n]==1)n--;
        else if(a[n]==3)a[n]=2;
        for(i=n;i;i--)
            if(!a[i])
            {
                if(a[i-1]==1)
                    a[i-1]=2,a[i]=-1;
                else if(a[i-1]==3)
                    a[i-1]=2,a[i]=2;
                else return false;
            }
        int tmp=0;
        for(i=1;i<=n;i++)
            if(a[i]!=-1)
                a[++tmp]]=a[i];
        n=tmp;
        for(i=1;i<=n;i++)
            a[i]--;
    }
    return true;
}

int main()
{
    int T,i,n;
    for(scanf("%d",&T);T;T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",a+i);
        puts(ck()?"TAK":"NIE");
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值