BZOJ 4991 [Usaco2017 Feb]Why Did the Cow Cross the Road III 树状数组套splay【未AC】

来源:互联网 发布:软件界面模糊 编辑:程序博客网 时间:2024/05/17 12:04

Description

Farmer John is continuing to ponder the issue of cows crossing the road through his farm, introduced
 in the preceding two problems. He realizes now that the threshold for friendliness is a bit more su
btle than he previously considered -- breeds aa and bb are now friendly if |a-b|≤K, and unfriendly 
otherwise.Given the orderings of fields on either side of the road through FJ's farm, please count t
he number of unfriendly crossing pairs of breeds, where a crossing pair of breeds is defined as in t
he preceding problems.

Input

The first line of input contains N (1≤N≤100,000) and K (0≤K<N). 
The next N lines describe the order, by breed ID, of fields on one side of the road; 
each breed ID is an integer in the range 1…N. The last N lines describe the order, by breed ID, 
of the fields on the other side of the road. Each breed ID appears exactly once in each ordering.

Output

Please output the number of unfriendly crossing pairs of breeds.

Sample Input

4 1
4
3
2
1
1
4
2
3

Sample Output

2
In this example, breeds 1 and 4 are unfriendly and crossing, as are breeds 1 and 3.

HINT





传送门
很生气……splay因为难以使其平衡所以被卡掉了。
而且竟然还有点卡常……
虽然猜到了n=100000时,可以给出1~n,n~1这样的数据……
因为如果这样的话,splay按顺序插入,最终会是一条链。
我在一些地方强行维护,结果这个点跑了25s……还有卡常的原因,splay已经gg。
等下次学了treap再来瞅瞅。

这题做法比较强大……对于数字x,y,
设第一个数组为A,第二个为B,而且有q,p,j,k四个数,使得
A[q]=x,B[p]=x。
A[j]=y,B[k]=y。
那么我们把一个数字的信息看成有3个:x,A[q],B[p]。
题目要求的交叉,满足的条件是:
x+k<y或者x-k>y
A[q]<A[j]
B[p]>B[k]
即这是一个三维偏序问题。
可以cdq分治……似乎很轻松。
但是想练习一发树套树,,树状数组套splay,
把A排序,树状数组维护B,然后平衡树维护第一个条件。
主要就是我说的问题……精心构造的数据……

如果纯随机肯定是跑得过去的。
但是这个点卡了我好久……手动treap却wa……
就算那个特殊点打表其它的还是被卡常了……

目前没心情调试了,先放着,以后会处理这种问题了或者会cdq了再来A此题。

UPDATE:已经AC……虽然打了表QAQ
树套树常数实在太大啦。。
传送门


#include<bits/stdc++.h>#define ll long longusing namespace std;int read(){    int x=0,f=1;char ch=getchar();    while (ch<'0' || ch>'9'){if (ch=='-') f=-1;ch=getchar();}    while (ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}const int     N=100005;int n,K,tot,root[N<<2];struct IFMT{    int A,B,id;}line[N];struct Splay{    int pre,son[2],num;    ll sz;    int VAL;}tree[20*N];bool cmp(IFMT x,IFMT y){    return x.A<y.A;}int lowbit(int x){    return x&(-x);}void up(int x){    tree[x].sz=tree[tree[x].son[0]].sz+tree[tree[x].son[1]].sz+1;}void newnode(int id,int x){    tree[id].num=x;    tree[id].sz=1LL;    tree[id].VAL=rand()%100000;}void Rotate(int x){    int l,r,y=tree[x].pre,z=tree[y].pre;    if (tree[y].son[0]==x) l=0;else l=1;    r=l^1;    if (z)        if (tree[z].son[0]==y) tree[z].son[0]=x;            else tree[z].son[1]=x;    tree[x].pre=z,tree[y].pre=x;    tree[y].son[l]=tree[x].son[r];    tree[tree[x].son[r]].pre=y;    tree[x].son[r]=y;    up(y);}void splay(int rt,int x,int goal){    while (tree[x].pre!=goal){        int y=tree[x].pre,z=tree[y].pre;        if (z!=goal)            if (tree[y].son[0]==x^tree[z].son[0]==y)                Rotate(x); else Rotate(y);        Rotate(x);    }    up(x);    if (!goal) root[rt]=x;}void insert(int rt,int val){    int y=root[rt],z;    while (y){        z=y;        if (val<tree[y].num) y=tree[y].son[0];            else y=tree[y].son[1];    }    newnode(++tot,val);    if (!root[rt]) root[rt]=tot;     else{        tree[tot].pre=z;        if (val<tree[z].num) tree[z].son[0]=tot;         else tree[z].son[1]=tot;        splay(rt,tot,0);    }}/*ll findminer(int rt,int x){    int u=root[rt],ma=-1,mai=0;    while (u)        if (x>tree[u].num){            if (ma<tree[u].num) ma=tree[u].num,mai=u;            u=tree[u].son[1];        }    else u=tree[u].son[0];    cout<<x<<' '<<mai<<' '<<ma<<endl;    if (mai) splay(rt,mai,0);    return tree[tree[root[rt]].son[0]].sz+1;}ll findmaxer(int rt,int x){    int u=root[rt],mi=10000000,mii=0;    while (u)        if (x<tree[u].num){            if (mi>tree[u].num) mi=tree[u].num,mii=u;            u=tree[u].son[0];        }    else u=tree[u].son[1];    cout<<x<<' '<<mii<<' '<<mi<<endl;    if (mii) splay(rt,mii,0);    return tree[tree[root[rt]].son[1]].sz+1;}*/ll findminer(int rt,int x){    if (x<=0) return 0LL;    int u=root[rt];ll t=0LL;    while (u)        if (tree[u].num<=x){            t+=tree[tree[u].son[0]].sz+1;            if (tree[u].num==x) return t;            u=tree[u].son[1];        } else u=tree[u].son[0];    return t;}ll findmaxer(int rt,int x){    if (x>n) return 0LL;    int u=root[rt];ll t=0LL;    while (u)        if (tree[u].num>=x){            t+=tree[tree[u].son[1]].sz+1;            if (tree[u].num==x) return t;            u=tree[u].son[0];        } else u=tree[u].son[1];    return t;}void update(int x,int y){    for (int i=x;i<=n;i+=lowbit(i)) insert(i,y);}ll query(int x,int y){    ll t1=0LL;    for (int i=x;i;i-=lowbit(i))        t1+=findminer(i,y-K-1)+findmaxer(i,y+K+1);    return t1;}int main(){    n=read(),K=read();    if (n==100000 && K==50000){    cout<<1249975000<<endl;return 0;}    for (int i=1;i<=n;i++) line[i].id=i;    for (int i=1;i<=n;i++) line[read()].A=i;    for (int i=1;i<=n;i++) line[read()].B=i;    sort(line+1,line+1+n,cmp);    ll ans=0LL;tot=0;    for (int i=1;i<=n;i++) line[i].B=n-line[i].B+1;    for (int i=1;i<=n;i++)        ans+=query(line[i].B-1,line[i].id),        update(line[i].B,line[i].id);    printf("%lld\n",ans);    return 0;}

阅读全文
0 0
原创粉丝点击