双面间谍(spy)

双面间谍

链接

分析:

  戳这

代码:

#include<cstdio>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<bitset>
using namespace std;
typedef long long LL;

inline int read() {
    int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
}

const int N = 200005;
int a[N], b[N], x[N], y[N], dx[N], dy[N];

struct SegmentTree{
    int Root[N], ls[N * 25], rs[N * 25], cnt[N * 25], Index, n, Now, disc[N]; 
    LL sum[N * 25], Ans;
    SegmentTree() { n = 0; }
    void Insert(int l,int r,int &now,int pre,int p) {
        if (!now) now = ++Index;
        sum[now] = sum[pre] + disc[p]; cnt[now] = cnt[pre] + 1;
        if (l == r) return ; 
        int mid = (l + r) >> 1;
        if (p <= mid) rs[now] = rs[pre], Insert(l, mid, ls[now], ls[pre], p);
        else ls[now] = ls[pre], Insert(mid + 1, r, rs[now], rs[pre], p);
    }
    void query(int l,int r,int now,int pre,int k) {
        if (l == r) { Now = disc[l]; return ; }
        int mid = (l + r) >> 1, x = cnt[ls[now]] - cnt[ls[pre]];
        if (k <= x)  {
            query(l, mid, ls[now], ls[pre], k);
            Ans += (sum[rs[now]] - sum[rs[pre]]) - 1ll * Now * (cnt[rs[now]] - cnt[rs[pre]]);
        }
        else {
            query(mid + 1, r, rs[now], rs[pre], k - x);
            Ans += 1ll * Now * x - (sum[ls[now]] - sum[ls[pre]]);
        }
    }
}T1, T2;

void solve() {
    int l = read(), r = read(); LL ans = 0;
    T1.Ans = 0, T1.Now = 0; 
    T1.query(0, T1.n, T1.Root[r], T1.Root[l - 1], (r - l + 1 + 1) / 2);
    ans += T1.Ans;
    
    T2.Ans = 0, T2.Now = 0; 
    T2.query(0, T2.n, T2.Root[r], T2.Root[l - 1], (r - l + 1 + 1) / 2);
    ans += T2.Ans;
    
    printf("%.2lf\n", ans / 2.0);    
}

signed main() {
    int n = read(), m = read(), cx = 1, cy = 1;
    for (int i = 1; i <= n; ++i) a[i] = read();
    for (int i = 1; i <= n; ++i) {
        b[i] = read();
        x[i] = a[i] + b[i], y[i] = a[i] - b[i];
        T1.disc[i] = x[i], T2.disc[i] = y[i];
    }
    sort(T1.disc + 1, T1.disc + n + 1);
    sort(T2.disc + 1, T2.disc + n + 1);
    for (int i = 2; i <= n; ++i) {
        if (T1.disc[i] != T1.disc[cx]) T1.disc[++cx] = T1.disc[i];
        if (T2.disc[i] != T2.disc[cy]) T2.disc[++cy] = T2.disc[i];
    }
    for (int i = 1; i <= n; ++i) {
        x[i] = lower_bound(T1.disc + 1, T1.disc + cx + 1, x[i]) - T1.disc;
        y[i] = lower_bound(T2.disc + 1, T2.disc + cy + 1, y[i]) - T2.disc;
    }
    for (int i = 1; i <= n; ++i) T1.n = max(T1.n, x[i]), T2.n = max(T2.n, y[i]);
    for (int i = 1; i <= n; ++i) {
        T1.Insert(0, T1.n, T1.Root[i], T1.Root[i - 1], x[i]);
        T2.Insert(0, T2.n, T2.Root[i], T2.Root[i - 1], y[i]);
    }
    while (m --) solve();
    return 0;
}

 

转载于:https://www.cnblogs.com/mjtcn/p/10568047.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值