zoukankan      html  css  js  c++  java
  • P2448 无尽的生命(树状数组+离散化)

    题目描述

    逝者如斯夫,不舍昼夜!

    叶良辰认为,他的寿命是无限长的,而且每天都会进步。

    叶良辰的生命的第一天,他有1点能力值。第二天,有2点。第n天,就有n点。也就是S[i]=i

    但是调皮的小A使用时光机,告诉他第x天和第y天,就可以任意交换某两天的能力值。即S[x]<-->S[y]

    小A玩啊玩,终于玩腻了。

    叶良辰:小A你给我等着,我有100种办法让你生不如死。除非能在1秒钟之内告知有多少对“异常对”。也就是说,最后的能力值序列,有多少对的两天x,y,其中x<y,但是能力值S[x]>S[y]?

    小A:我好怕怕啊。

    于是找到了你。

    输入输出格式

    输入格式:

    第一行一个整数k,表示小A玩了多少次时光机

    接下来k行,x_i,y_i,表示将S[x_i]与S[y_i]进行交换

    输出格式:

    有多少“异常对”

    输入输出样例

    输入样例#1: 复制
    2
    4 2
    1 4
    输出样例#1: 复制
    4
    

    说明

    样例说明

    最开始是1 2 3 4 5 6...

    然后是 1 4 3 2 5 6...

    然后是 2 4 3 1 5 6...

    符合的对是[1 4] [2 3] [2 4] [3 4]

    对于30%的数据,x_i,y_i <= 2000

    对于70%的数据, x_i,y_i <= 100000

    对于100%的数据, x_i.y_i <= 2^31-1 k<=100000

    6024

    题解:方法千篇一律,主要是自己在草稿纸上模拟一遍,才能领会其中精妙所在!

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=100010;
    int Hash[maxn<<1],c[maxn<<1],lsh[maxn<<1];
    int cnt,top,n,m;
    pair<int,int>P[maxn];
    int lowbit(int x){return x&-x;}
    void update(int x,int v)
    {
        for(int i=x;i<=m;i+=lowbit(i))
            c[i]+=v;
    }
    ll sum(int x)
    {
        ll ans=0;
        for(int i=x;i>=1;i-=lowbit(i))
            ans+=c[i];
        return ans;
    }
    int main()
    {
        int k;
        cin>>k;
        for(int i=1;i<=k;i++){
            cin>>P[i].first>>P[i].second;
            Hash[++cnt]=P[i].first;
            Hash[++cnt]=P[i].second;//先都放入Hash数组里,之后排序去重
        }
        sort(Hash+1,Hash+1+cnt);
        m=unique(Hash+1,Hash+1+cnt)-Hash-1;
        for(int i=1;i<=m;i++)lsh[i]=i;//记录原始状态
        for(int i=1;i<=k;i++){
            int pos1=lower_bound(Hash+1,Hash+1+m,P[i].first)-Hash;
            int pos2=lower_bound(Hash+1,Hash+1+m,P[i].second)-Hash;
            swap(lsh[pos1],lsh[pos2]);//找到对应位置进行相应操作
        }
        ll ans=0;
        for(int i=m;i>=1;i--){
            ans+=sum(lsh[i]-1);//单点求逆序对
            update(lsh[i],1);//更新单点
            ll len=Hash[i]-Hash[i-1]-1;//求连续区间长度
            ans+=len*sum(i-1);//连续的不变区间,可以将它看作 i 这个数!
            if(i!=1)update(i-1,len);//最后一个不用更新了(也不能更新,会在更新中死循环,因为0的lowbit是0)
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    友链
    P2572 [SCOI2010]序列操作
    「THP3考前信心赛」解题报告
    DP中的树上边/点覆盖问题
    P3413 SAC#1
    luoguP6754 [BalticOI 2013 Day1] Palindrome-Free Numbers
    睿智错误
    常见套路?
    奇怪的点子
    最近做过一些比较好的题
  • 原文地址:https://www.cnblogs.com/cherish-lin/p/10964431.html
Copyright © 2011-2022 走看看