绍一集训Round#2

Preface

感受此次的题目是真的太水了,多是为了让咱们涨一波信心的吧。node

不过最后一题没有想到那种玄学作法仍是太菜了,仍是要一波姿式的啊。git


交换

一道入门难度题,根据排序不等式(又或是简单推导能够发现直接把一个数换到它该去的地方是确定不会更差的。spa

所以咱们直接模拟交换的过程便可,复杂度\(O(n)\)code

CODE排序

#include<cstdio>
#include<cctype>
using namespace std;
const int N=1000005;
int n,a[N],id[N],ans;
inline char tc(void)
{
    static char fl[100000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
    x=0; char ch; while (!isdigit(ch=tc()));
    while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
}
inline void swap(int &a,int &b)
{
    int t=a; a=b; b=t;
}
int main()
{
    freopen("swap.in","r",stdin); freopen("swap.out","w",stdout);
    register int i; read(n);
    for (i=1;i<=n;++i)
    read(a[i]),id[a[i]]=i;
    for (i=1;i<=n;++i)
    if (a[i]^i) id[a[i]]=id[i],swap(a[i],a[id[i]]),id[i]=i,++ans;
    return printf("%d",ans),0;
}

兔子抓狼

首先分析对于狼来讲什么状况是最优的get

若是一只兔子能够炸到它,那么它早晚会被这只兔子给炸了,不然兔子会一直保持在它的右边。it

所以,咱们分析出,狼直接走回家是对于它来讲最好的选择io

而后就很简单了,咱们再来考虑兔子,因为若是一只兔子能够在狼回家的路上炸到狼,咱们为了简化问题假定让兔子所有跑到狼的家门口去炸它。入门

这样咱们对于全部兔子到达狼的家的距离开一个维护一下,而后每次取出堆顶判断是否能够炸到狼便可class

CODE

#include<cstdio>
#include<cctype>
#include<queue>
#include<cmath>
using namespace std;
typedef double DB;
const int N=500005,tar=10000000;
int n,ans,x,y,t,tot;
priority_queue < DB,vector<DB>,greater<DB> > small;
inline char tc(void)
{
    static char fl[100000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
    x=0; char ch; int flag=1; while (!isdigit(ch=tc())) flag=ch^'-'?1:-1;
    while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc())); x*=flag;
}
int main()
{
    freopen("rabbit.in","r",stdin); freopen("rabbit.out","w",stdout);
    register int i; read(n); read(t);
    for (i=1;i<=n;++i)
    read(x),read(y),small.push((DB)sqrt(1LL*(x-tar)*(x-tar)+1LL*y*y));
    while (!small.empty())
    if (small.top()<=(DB)tar+tot) tot+=t,++ans,small.pop(); else break;
    return printf("%d",ans),0;
}

魔法

首先你要知道一个东西:01Trie

这个很简单,想当于建出一棵树,每个节点都是一个0/1值。从根出发的某条路径上的点表明的就是一个二进制下的数

而后咱们发现这个东西就能够很好的处理xor了

咱们先把全部的点插入0/1Trie中,每一次查询的时候至关与询问大于等于一个数的两数xor值。

咱们同时跳两条链,每次判断当前节点的值是否小于所求的点,如果则这两点必然异位

统计的时候也有个小Trick,分红一段一段来搞又快又方便

CODE

#include<cstdio>
#include<cctype>
using namespace std;
typedef long long LL;
const int N=50005,P=60;
struct Trie
{
    int ch[2],size;
}node[N*P];
int n,tot=1; LL x,ans,s=1;
inline char tc(void)
{
    static char fl[100000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
    x=0; char ch; while (!isdigit(ch=getchar()));
    while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=getchar()));
}
inline void read(LL &x)
{
    x=0; char ch; while (!isdigit(ch=getchar()));
    while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=getchar()));
}
inline void insert(LL x,int &now,int d)
{
    if (!now) now=++tot; ++node[now].size;
    if (!(~d)) return;
    if (x&(1LL<<d)) insert(x,node[now].ch[1],d-1); else insert(x,node[now].ch[0],d-1);
}
inline void query(int x,int y,LL s,int d)
{
    if (!x||!y) return; if ((1LL<<d+1)<=s) return;
    if ((1LL<<d)>=s)
    {
        ans+=1LL*node[node[x].ch[0]].size*node[node[y].ch[1]].size+1LL*node[node[x].ch[1]].size*node[node[y].ch[0]].size;
        query(node[x].ch[0],node[y].ch[0],s,d-1); query(node[x].ch[1],node[y].ch[1],s,d-1);
    } else query(node[x].ch[0],node[y].ch[1],s-(1LL<<d),d-1),query(node[x].ch[1],node[y].ch[0],s-(1LL<<d),d-1);
}
int main()
{
    freopen("magic.in","r",stdin); freopen("magic.out","w",stdout);
    register int i; read(n);
    for (i=1;i<=n;++i)
    {
        read(x); int now=1; insert(x,now,P-1);
    }
    for (i=1;i<=19;++i,s*=10) query(1,1,s,P-1);
    return printf("%lld",ans>>1),0;
}
相关文章
相关标签/搜索