再次求助卡常
查看原帖
再次求助卡常
132533
FutaRimeWoawaSete楼主2021/6/1 23:04

先不说Cache,大家看一下这代码还有没有什么可以卡常的地方啊,调块长也没用。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int Len = 1e5 + 5, T = 205 , SIZE = 505;
int n, m, Num[Len][SIZE][2], t, L[SIZE], R[SIZE], pos[Len], suf[SIZE][T], pre[SIZE][T];
int sizt,val[Len];
long long Ans[SIZE][SIZE];
struct node {
    int idx, val;
} a[Len];
bool cmp(node x, node y) { return x.val < y.val; }
int c[Len];
inline int lowbit(int x) { return x & (-x); }
inline void add(int x, int w) {
    while (x <= n) c[x] += w, x += lowbit(x);
}
inline int qry(int x) {
    int res = 0;
    while (x) res += c[x], x -= lowbit(x);
    return res;
}
inline int Calc(int l, int r) {
    int fr = L[l], se = L[r];
    int num = 0;
    while (fr <= R[l] && se <= R[r]) {
        if (a[fr].val < a[se].val)
            fr++;
        else
            se++, num += R[l] - fr + 1;
    }
    return num;
}
int Used[Len][2], len[2];
inline int Cal() {
    int fr = 1, se = 1;
    int res = 0;
    while (fr <= len[0] && se <= len[1]) {
        if (Used[fr][0] < Used[se][1])
            fr ++;
        else
            se ++, res += len[0] - fr + 1;
    }
    return res;
}
inline long long qry(int l, int r) {
    int LL = pos[l], RR = pos[r];
    long long res = 0;
    if(LL == RR) 
    {
    	int res = pre[LL][r - L[RR] + 1] - pre[LL][l - 1 - L[RR] + 1];
    	len[0] = len[1] = 0;
    	for(int i = L[LL] ; i <= R[LL] ; i ++)
    	{
    		if(l <= a[i].idx && a[i].idx <= r) Used[++ len[1]][1] = a[i].val;
    		else if(a[i].idx < l) Used[++ len[0]][0] = a[i].val;
		}
		return res - Cal();
	}
    res += Ans[LL + 1][RR - 1] + suf[LL][l - L[LL] + 1] + pre[RR][r - L[RR] + 1];
    for (int i = l; i <= R[LL]; i ++) res += Num[val[i]][RR - 1][0] - Num[val[i]][LL][0];
    for (int i = L[RR]; i <= r; i ++) res += Num[val[i]][RR - 1][1] - Num[val[i]][LL][1];
    len[0] = len[1] = 0;
    for (int i = L[LL]; i <= R[LL]; i++)
        if (l <= a[i].idx && a[i].idx <= r)
            Used[++ len[0]][0] = a[i].val;
    for (int i = L[RR]; i <= R[RR]; i++)
        if (l <= a[i].idx && a[i].idx <= r)
            Used[++ len[1]][1] = a[i].val;
    return res + Cal();
}
inline long long read() {
    char ch = getchar(); int x = 0, f = 1;
    while(ch < '0' || ch > '9') {
        if(ch == '-') f = -1;
        ch = getchar();
    } while('0' <= ch && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    } return x * f;
}
inline void write(long long x)
{
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}
signed main() {
	//freopen("1.in","r",stdin);
	//freopen("1.out","w",stdout);
    n = read() , m = read();
    for (int i = 1; i <= n; i++) {
        a[i].val = read();
        a[i].idx = i;
    }
    for (int i = 1; i <= n; i++) val[i] = a[i].val;
    t = 205;
    sizt = n / t;
    for (int i = 1; i <= sizt; i++) L[i] = (i - 1) * t + 1, R[i] = i * t;
    if (R[sizt] < n) {
        sizt ++;
        L[sizt] = R[sizt - 1] + 1;
        R[sizt] = n;
    }
    for (int i = 1; i <= sizt; i++)
        for (int j = L[i]; j <= R[i]; j++) pos[j] = i;
    /*for (int now = 1; now <= sizt; now++) {
        for (int len = 2; len <= R[now] - L[now] + 1; len++) {
            for (int i = L[now]; i + len - 1 <= R[now]; i++) {
                int j = i + len - 1;
				#define I i - L[now] + 1
				#define J j - L[now] + 1
                Anss[now][I][J] = Anss[now][I + 1][J] + Anss[now][I][J - 1] - Anss[now][I + 1][J - 1] +
                                  (a[i].val > a[j].val);
				//printf("%d\n",Anss[now][I][J]);
				#undef I
				#undef J
				
            }
        }
    }*/
    for (int i = 1; i <= sizt; i++) {
        int sim = 0;
        for (int j = L[i]; j <= R[i]; j++) {
            sim += qry(n) - qry(a[j].val);
            pre[i][j - L[i] + 1] = sim;
            add(a[j].val , 1);
        }
        for (int j = L[i]; j <= R[i]; j++) add(a[j].val, -1);
        sim = 0;
        for (int j = R[i]; j >= L[i]; j--) {
            sim += qry(a[j].val - 1);
            suf[i][j - L[i] + 1] = sim;
            add(a[j].val , 1);
        }
        for (int j = L[i]; j <= R[i]; j++) add(a[j].val, -1);
        //printf("%d\n",i);
       // for(int j = L[i] ; j <= R[i] ; j ++) printf("%d ",pre[i][j - L[i] + 1]);
        //puts("");
        //for(int j = L[i] ; j <= R[i] ; j ++) printf("%d ",suf[i][j - L[i] + 1]);
        //puts("");
        Ans[i][i] = pre[i][R[i] - L[i] + 1];
    }
    for (int i = 1; i <= sizt; i++) {
        for (int j = L[i]; j <= R[i]; j++)
            Num[val[j] + 1][i][0] ++, Num[val[j] - 1][i][1] ++;           //记录比它小的和大的
        for (int j = n ; j >= 1; j --) Num[j][i][1] += Num[j + 1][i][1];  //处理比它大的
        for (int j = 1 ; j <= n; j ++) Num[j][i][0] += Num[j - 1][i][0];  //处理比它小的
        for(int j = 1 ; j <= n ; j ++)
		{ 
			//if(j == 6 && i == 2) printf("#%d\n",Num[j][i][0]);
            Num[j][i][0] += Num[j][i - 1][0];
            Num[j][i][1] += Num[j][i - 1][1];
            //printf("%d %d %d %d\n",i,j,Num[j][i][0],Num[j][i][1]);
        }
    }
    for (int i = 1; i <= sizt; i++) sort(a + L[i], a + R[i] + 1, cmp);
    for (int len = 2; len <= sizt; len++) {
        for (int i = 1; i + len - 1 <= t; i++) {
            int j = i + len - 1;
            Ans[i][j] = Ans[i][j - 1] + Ans[i + 1][j] - Ans[i + 1][j - 1] + Calc(i , j);
            //printf("%d\n",Ans[i][j]);
        }
    }

    long long lstans = 0;
    for (int i = 1; i <= m; i++) {
        long long l, r;
        l = read() , r = read();
        l = l ^ lstans, r = r ^ lstans;
        if(l > r) swap(l , r); 
        write(lstans = qry(l , r)) , putchar('\n');
    }
    return 0;
}
/*
10 1
6 4 5 1 10 7 8 9 3 2 
1 7
*/
2021/6/1 23:04
加载中...