# 2017.7.22模拟赛被虐记录

map真TM的慢。。早知道就不图方便自己打个数组记录

200 -> 70
EXM？200分rank2啊

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
{
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;

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)$O(nlogn)$可持久化线段树加堆
Sol2:O(nlog2n)$O(nlog^2n)$点分树+超级钢琴
Sol3:O(nlog2n)$O(nlog^2n)$点分树+二分答案+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;
{
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;

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

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;
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];
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);
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;
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);
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()
{

for(int i=2;i<=n;i++)
{
int a,b,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得出

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

char c;
{
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");
}

}