紹一集訓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;
}
相關文章
相關標籤/搜索