cf 240 div2

B. Mashmokh and Tokens

//#pragma warning (disable: 4786)
//#pragma comment (linker, "/STACK:16777216")
//HEAD
#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
//LOOP
#define FE(i, a, b) for(int i = (a); i <= (b); ++i)
#define FD(i, b, a) for(int i = (b); i>= (a); --i)
#define REP(i, N) for(int i = 0; i < (N); ++i)
#define CLR(A,value) memset(A,value,sizeof(A))
#define CPY(a, b) memcpy(a, b, sizeof(a))
#define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
//INPUT
#define RI(n) scanf("%d", &n)
#define RII(n, m) scanf("%d%d", &n, &m)
#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define RS(s) scanf("%s", s)
//OUTPUT
#define WI(n) printf("%d\n", n)
#define WS(s) printf("%s\n", s)

typedef long long LL;
const int INF = 1000000007;
const double eps = 1e-10;
const int MAXN = 1000010;

int n, a, b;
int main ()
{
    RIII(n, a, b);
    int p = 0;
    while (n--)
    {
        int x;
        RI(x);
        if (p) printf(" "); p = 1;
        cout << 1LL * x * a % b / a;
    }
    puts("");
    return 0;
}

E. Mashmokh and Reverse Operation

将逆序数总结果按照区间大小分层,利用归并排序预处理每层逆序数之和,之后针对每层每次修改求和

//#pragma warning (disable: 4786)
//#pragma comment (linker, "/STACK:16777216")
//HEAD
#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
//LOOP
#define FE(i, a, b) for(int i = (a); i <= (b); ++i)
#define FD(i, b, a) for(int i = (b); i>= (a); --i)
#define REP(i, N) for(int i = 0; i < (N); ++i)
#define CLR(A,value) memset(A,value,sizeof(A))
#define CPY(a, b) memcpy(a, b, sizeof(a))
#define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
//INPUT
#define RI(n) scanf("%d", &n)
#define RII(n, m) scanf("%d%d", &n, &m)
#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define RS(s) scanf("%s", s)
//OUTPUT
#define WI(n) printf("%d\n", n)
#define WS(s) printf("%s\n", s)

typedef long long LL;
const int INF = 1000000007;
const double eps = 1e-10;
const int maxn = 1111111;

LL s[2][30];
int now[30];
LL pow2[30];
///0 1     n(wei0)
///n n-1   0

int A[maxn], T[maxn];
int n, m;
void merge_sort(int *A, int x, int y, int *T, int level)///求每层的严格逆序数
{
    if (y <= x) return ;
    int m = x + (y - x) / 2;
    int p = x, q = m + 1, i = x;
    merge_sort(A, x, m, T, level + 1);
    merge_sort(A, m + 1, y, T, level + 1);
    while (p <= m|| q <= y)
    {
        if (q > y || (p <= m && A[p] <= A[q])) T[i++] = A[p++];
        else
        {
            s[0][level] += m - p + 1;
            T[i++] = A[q++];
        }
    }
    p = m, q = y, i = y;
    while (p >= x && q > m)///求每层的严格顺序数
    {
        if (q <= m || (p >= x && A[p] >= A[q])) T[i--] = A[p--];
        else
        {
            s[1][level] += p - x + 1;
            T[i--] = A[q--];
        }
    }
    for (int i = x; i <= y; i++) A[i] = T[i];
}
int main ()
{
    pow2[0] = 1;
    for (int i = 1; i <= 22; i++)
        pow2[i] = pow2[i - 1] * 2;

    RI(n);
    REP(i, pow2[n]) RI(A[i]);
    merge_sort(A, 0, pow2[n] - 1, T, 0);

    RI(m);
    while (m--)
    {
        int x; RI(x);
        for (int i = x; i >= 1; i--)///子期间大小2^i
        {
            int y = n - i;///子区间个数2^y,同时也是递归的第y层
            now[y] ^= 1;
        }
        LL ans = 0;
        for (int i = 0; i <= n; i++) ans += s[now[i]][i];
        cout << ans << endl;
    }
    return 0;
}


inplace_merge()是对两个已排好序的序列,就地排序

对于A数组的[l, m][m + 1, r]

调用方法是inplace_merge(A + l, A + m + 1, A + r + 1);一般效率是O(n),最差n*log(n)

//#pragma warning (disable: 4786)
//#pragma comment (linker, "/STACK:16777216")
//HEAD
#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
//LOOP
#define FE(i, a, b) for(int i = (a); i <= (b); ++i)
#define FD(i, b, a) for(int i = (b); i>= (a); --i)
#define REP(i, N) for(int i = 0; i < (N); ++i)
#define CLR(A,value) memset(A,value,sizeof(A))
#define CPY(a, b) memcpy(a, b, sizeof(a))
#define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
//INPUT
#define RI(n) scanf("%d", &n)
#define RII(n, m) scanf("%d%d", &n, &m)
#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define RS(s) scanf("%s", s)
//OUTPUT
#define WI(n) printf("%d\n", n)
#define WS(s) printf("%s\n", s)

typedef long long LL;
const int INF = 1000000007;
const double eps = 1e-10;
const int maxn = 1111111;

LL s[2][30];
int now[30];
LL pow2[30];
///0 1     n(wei0)
///n n-1   0

int A[maxn];
int n, m;
void merge_sort(int *A, int x, int y, int level)///求每层的严格逆序数
{
    if (y <= x) return ;
    int m = x + (y - x) / 2;
    int p = x, q = m + 1, i = x;
    merge_sort(A, x, m, level + 1);
    merge_sort(A, m + 1, y, level + 1);
    int s0 = x, s1 = x;
    for (int i = m + 1; i <= y; i++)
    {
        for (; s0 <= m; s0++) if (A[s0] > A[i]) break;
        for (; s1 <= m; s1++) if (A[s1] >= A[i]) break;
        s[0][level] += m - s0 + 1;
        s[1][level] += s1 - x;
    }
    inplace_merge(A + x, A + m + 1, A + y + 1);///就地排序两个已经排好的序列
}
int main ()
{
    pow2[0] = 1;
    for (int i = 1; i <= 22; i++)
        pow2[i] = pow2[i - 1] * 2;

    RI(n);
    REP(i, pow2[n]) RI(A[i]);
    merge_sort(A, 0, pow2[n] - 1, 0);
    RI(m);
    while (m--)
    {
        int x; RI(x);
        for (int i = x; i >= 1; i--)///子期间大小2^i
        {
            int y = n - i;///子区间个数2^y,同时也是递归的第y层
            now[y] ^= 1;
        }
        LL ans = 0;
        for (int i = 0; i <= n; i++) ans += s[now[i]][i];
        cout << ans << endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值