萌新刚学OI,再求Ynoi
查看原帖
萌新刚学OI,再求Ynoi
371968
ningago寄寄人楼主2022/6/21 19:53

上个帖后,我成功把 10TLE(3s-4s)卡成了 9TLE(2-3s)+1WA……

(对拍1e4的数据没问题

看到题解区有篇blog算法一样,而且笔者说不用卡常,还用了许多加常数的#define int long longusing namespace std,百思不得其解,求助大佬卡常

#include <cstring>
#include <cmath>
#include <algorithm>
#include <ctime>

#define N 100010

using std::sort;
using std::max;
using std::min;

int n,m,a[N];

inline int read()
{
    int x = 0,f = 1;
    char c = getchar();
    while(c < '0' || '9' < c)
    {
        if(c == '-')
            f = -1;
        c = getchar();
    }
    while('0' <= c && c <= '9')
    {
        x = (x << 3) + (x << 1) + (c ^ 48);
        c = getchar();
    }
    return x * f;
}

int len,idx,belong[N],L[N],R[N],d[N],lazy[N];

inline void build()
{
    len = sqrt(n);
    idx = n / len;
    if(n % len) idx++;
    for(int i = 1;i <= n;i++)
    {
        belong[i] = (i - 1) / len + 1;
    }
    for(int i = 1;i <= idx;i++)
    {
        L[i] = (i - 1) * len + 1;
        R[i] = i * len;
    }
    R[idx] = n;
    memcpy(d,a,sizeof(a));
    for(int i = 1;i <= idx;i++)
        sort(d + L[i],d + 1 + R[i]);
}

inline void add(int x,int y,int z)
{
    if(belong[x] == belong[y])
    {
        for(int i = x;i <= y;i++)
            a[i] += z;
        for(int i = L[belong[x]];i <= R[belong[x]];i++)
            d[i] = a[i];
        sort(d + L[belong[x]],d + R[belong[x]] + 1);
        return;
    }
    int from = belong[x];
    for(int i = x;i <= R[from];i++)
    {
        a[i] += z;
    }
    for(int i = L[from];i <= R[from];i++)
    {
        d[i] = a[i];
    }
    sort(d + L[from],d + R[from] + 1);

    from = belong[y];
    for(int i = L[from];i <= y;i++)
    {
        a[i] += z;
    }
    for(int i = L[from];i <= R[from];i++)
    {
        d[i] = a[i];
    }
    sort(d + L[from],d + R[from] + 1);

    for(int i = belong[x] + 1;i <= belong[y] - 1;i++)
    {
        lazy[i] += z;
    }
}

int tmp[N],top;

inline int get_min(int x,int y)
{
    int res = 0x3f3f3f3f;
    if(belong[x] == belong[y])
    {
        for(int i = x;i <= y;i++)
            res = min(res,a[i] + lazy[belong[x]]);
        return res;
    }
    for(int i = x;i <= R[belong[x]];i++)
    {
        res = min(res,a[i] + lazy[belong[x]]);
    }
    for(int i = L[belong[y]];i <= y;i++)
    {
        res = min(res,a[i] + lazy[belong[y]]);
    }
    for(int i = belong[x] + 1;i <= belong[y] - 1;i++)
    {
        res = min(res,d[L[i]] + lazy[i]);
    }
    return res;
}

inline int get_max(int x,int y)
{
    int res = -0x3f3f3f3f;
    if(belong[x] == belong[y])
    {
        for(int i = x;i <= y;i++)
            res = max(res,a[i] + lazy[belong[x]]);
        return res;
    }
    for(int i = x;i <= R[belong[x]];i++)
    {
        res = max(res,a[i] + lazy[belong[x]]);
    }
    for(int i = L[belong[y]];i <= y;i++)
    {
        res = max(res,a[i] + lazy[belong[y]]);
    }
    for(int i = belong[x] + 1;i <= belong[y] - 1;i++)
    {
        res = max(res,d[R[i]] + lazy[i]);
    }
    return res;
}

inline int check(int x,int y,int mid)
{
    int ck = 0; //printf("l = %d,r = %d,mid = %d\n",l,r,mid);
    for(int i = x;i <= R[belong[x]];i++)
    {
        if(a[i] + lazy[belong[x]] <= mid)
		{
			//printf("+a[%d] = %d\n",i,a[i]);
            ck++;
		}
    }
    for(int i = L[belong[y]];i <= y;i++)
    {
        if(a[i] + lazy[belong[y]] <= mid)
		{
			//printf("+a[%d] = %d\n",i,a[i]);
            ck++;
		}
    }
    for(int i = belong[x] + 1;i <= belong[y] - 1;i++)
    {
        int ll = L[i],rr = R[i],mmid,aans = L[i] - 1;
        if(d[L[i]] + lazy[i] > mid)
            continue;
        if(d[R[i]] + lazy[i] <= mid)
        {
            ck += R[i] - L[i] + 1;
            continue;
        }
		while(ll <= rr)
		{
			mmid = ll + rr >> 1;
			if(d[mmid] + lazy[i] <= mid)
			{
				ll = mmid + 1;
				aans = mmid;
			}
			else
				rr = mmid - 1;
		}
		//printf("i = %d,kuai = %d to %d,aans = %d\n",i,L[i],R[i],aans);
        ck += aans - L[i] + 1;
    }
    return ck;
}

inline int query(int x,int y,int k)
{
    if(k < 1 || k > y - x + 1)
        return -1;
    if(belong[x] == belong[y])
    {
		//printf("A\n");
        top = 0;
        
        for(int i = x;i <= y;i++)
            tmp[++top] = a[i] + lazy[belong[x]];
        nth_element(tmp + 1,tmp + k,tmp + 1 + top);
        return tmp[k];
    }
	//printf("B\n");
    int l = get_min(x,y),r = get_max(x,y),mid,ans = -1;
    
    if(k == 1)
        return l;
    if(k == y - x + 1)
        return r;
	//printf("l = %d,r = %d\n",l,r);
    while(l <= r)
    {
       
        mid = l + r >> 1;
		//printf("mid = %d,check = %d,k = %d\n",mid,check,k);
		if(check(x,y,mid) >= k)
        {
            ans = mid;
            r = mid - 1;
        }
        else
            l = mid + 1;
    }
	return ans;
}/*     4 5
      3     6
      +     +
1 2 3 4 5 6 7*/

void write(int a)
{
    if(a < 0){
        putchar('-');
        a = -a;
    }
    if(a > 9)
        write(a / 10);
    putchar(a % 10 + '0');
}

int main()
{
    //double tim = time(0);
    //别管这个double
	freopen("maker.in","r",stdin);
	freopen("std.out","w",stdout);
    n = read(),m = read();
    for(int i = 1;i <= n;i++)
        a[i] = read();
    build();
    int op,l,r,k;
    while(m--)
    {
        op = read(),l = read(),r = read(),k = read();
        if(op == 0)
			add(l,r,k);
		else
        {
			write(query(l,r,k));
            putchar('\n');
        }
    }
    //printf("time:%.5f\n",time(0) - tim);
	return 0;
}
2022/6/21 19:53
加载中...