列表

详情


NC204649. 久岛 鸥

描述

「你要去哪里」

鸥「……」

「我记得,你的本体,现在应该是在外国对吧」

「你是要回那里去吗」

鸥「……」

鸥「不是的」

鸥慢慢地摇了摇头。 然后,望向了天空。
望向了,那闪耀着无数繁星的,那无比遥远的天空。

鸥「是一个更加——」

鸥「遥远的地方」

「更加遥远的地方……?」
天空中,n 颗星星构成了一个序列,第 i 颗星有一个属性 ai
久岛鸥需要回答,来自星空的 m 个询问。
每个询问给出一个区间 [l,r] 和一个正整数 k,鸥需要回答区间内所有星星属性的出现次数中,第 k 大的出现次数是多少,不存在则输出 0。

鸥不会做,于是找到了牛牛。牛牛思考了一会,就会做了。
然而,一些意想不到不到的事情发生了,有些时候,询问会根据上一次的回答而改变,这被称之为“强制在线
于是,牛牛不会了,然后就找到了你,希望你能够协助解决这个问题。

输入描述

第一行三个正整数 n,m 和 type,分别表示星星序列长度、询问次数和强制在线参数。
接下来一行 n 个正整数,其中第 i 个正整数表示序列中的第 i 个数 ai
接下来 m 行,每行三个整数 l,r 和 k,表示一次询问。
若强制在线参数 type=1 则实际询问的 l',r' 和 k' 由输入的 l,r 和 k 经以下运算得到:
l' = l xor lastans
r' = r xor lastans
k' = k xor lastans
其中 xor 为按位异或运算,lastans 为上次询问的答案,初始时 lastans=0。

输出描述

共 m 行,每行输出一个整数表示你的答案。

示例1

输入:

10 10 1
2 3 1 1 4 4 1 2 1 4
8 10 2
4 8 0
7 8 3
11 11 2
3 7 0
0 0 0
5 5 1
4 7 0
3 1 3
3 11 0

输出:

1
2
3
1
2
0
1
2
1
4

说明:

10 次询问真实的 (l,r,k) 经解密依次是:
(8,10,2), (5,9,1), (5,10,1), (8,8,1), (2,6,1), (2,2,2), (5,5,1), (5,6,1), (1,3,1), (2,10,1)

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 2292ms, 内存消耗: 200552K, 提交时间: 2020-04-30 07:26:07

#include<bits/stdc++.h>
using namespace std;
const int block=316,si=304,N=1e5+100;
int n,m,t,q,s[N],L[N],R[N],res[305],sum[N][345],a[N],type,vis[345][345][305];
vector<int>v,f[N];
bool vv[N];
void add(int x)
{
    if(a[x]==0) return;
    res[s[a[x]]]--;
    s[a[x]]++;
    res[s[a[x]]]++;
}
int get(int l,int r,int x)
{
    return upper_bound(f[x].begin(),f[x].end(),r)-upper_bound(f[x].begin(),f[x].end(),l-1);
}
int main()
{
    scanf("%d%d%d",&n,&t,&type);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),s[a[i]]++;
    for(int i=1;i<=n;i++)
        if(s[i]>si) v.push_back(i);
    for(int i=0;i<v.size();i++)
        for(int j=1;j<=n;j++)
        {
            sum[j][i]=sum[j-1][i]+(a[j]==v[i]);
            if(a[j]==v[i]) a[j]=0;
        }
    memset(s,0,sizeof(s));
    m=n/block;
    for(int i=1;i<=m;i++) L[i]=n;
    for(int i=1;i<=n;i++) L[i/block]=min(L[i/block],i),R[i/block]=max(R[i/block],i);
    for(int i=1;i<=m;i++)
    {
        memset(s,0,sizeof(s));
        memset(res,0,sizeof(res));
        for(int j=i;j<=m;j++)
        {
            for(int k=L[j];k<=R[j];k++) add(k);
            memcpy(vis[i][j],res,sizeof(res));
        }
    }
    for(int i=1;i<=n;i++)
        if(a[i]) f[a[i]].push_back(i);
    int lastans=0;
    while(t--)
    {
        int l,r,k;scanf("%d%d%d",&l,&r,&k);
        if(type==1) l^=lastans,r^=lastans,k^=lastans;
        int le=l/block,ri=r/block;
        if(l!=L[le]) le++;
        if(r!=R[ri]) ri--;
        vector<int>b;
        if(le>ri)
        {
             memset(res,0,sizeof res);
             for(int i=l;i<=r;i++)
                if(a[i]&&!vv[a[i]])
                b.push_back(a[i]),vv[a[i]]=true;
        }
        else
        {
            memcpy(res,vis[le][ri],sizeof(res));
            for(int i=l;i<L[le];i++)
                if(a[i]&&!vv[a[i]])
                b.push_back(a[i]),vv[a[i]]=true;
            for(int i=R[ri]+1;i<=r;i++)
                if(a[i]&&!vv[a[i]])
                b.push_back(a[i]),vv[a[i]]=true;
        }
        for(int x:b)
        {
            vv[x]=false;
            if(le<=ri)
                res[get(L[le],R[ri],x)]--;
            res[get(l,r,x)]++;
        }
        vector<int>vc;
        for(int i=0;i<v.size();i++)
        {
            if(sum[r][i]-sum[l-1][i]<=si) res[sum[r][i]-sum[l-1][i]]++;
            else vc.push_back(sum[r][i]-sum[l-1][i]);
        }
        if(k<=vc.size())
        {
            sort(vc.begin(),vc.end(),greater<int>());
            printf("%d\n",lastans=vc[k-1]);
        }
        else
        {
            k-=vc.size();
            lastans=0;
            for(int i=si;i>=1;i--)
            {
                k-=res[i];
                if(k<=0)
                {
                    lastans=i;break;
                }
            }
            printf("%d\n",lastans);
        }
    }
}

C++(clang++11) 解法, 执行用时: 4856ms, 内存消耗: 520336K, 提交时间: 2021-04-18 11:24:22

#include<bits/stdc++.h>
#define REPI(n) for(int i=0;i<(n);++i)
#define REPJ(n) for(int j=0;j<(n);++j)
#define FOR(v,s,e) for(int (v)=(s);(v)<(e);++(v))
#define MSET(v,a) memset(a,v,sizeof(a))
#define MAX(a,b) (a)>(b)?(a):(b)
#define MIN(a,b) (a)<(b)?(a):(b)
typedef long long ll;
using namespace std;
int readtmp;
inline int read(int& v = readtmp) {
	scanf("%d", &v);
	return v;
}
const int maxn = 1e5 + 7;
const int maxl = 660;

int n, m, type;
int l, r, k;
int a[maxn];
int cnt[maxl][maxn];
int cct[maxl][maxn];

int smpl[maxl];
int smpr[maxl];
int smpnum = 0;

int ln, rn;
int *cntn, *cctn;

inline void addStar(int star) {
	cctn[cntn[star]]--;
	cctn[++cntn[star]]++;
}

inline void rmvStar(int star) {
	cctn[cntn[star]]--;
	cctn[--cntn[star]]++;
}


inline void move(int l, int r) {
	while (rn < r) addStar(a[++rn]);
	while (ln > l) addStar(a[--ln]);
	while (rn > r) rmvStar(a[rn--]);
	while (ln < l) rmvStar(a[ln++]);
}

void setsmp(int l, int r) {
	ln = 1;
	rn = 0;
	cntn = cnt[smpnum];
	cctn = cct[smpnum];
	cctn[0] = maxn;
	move(l, r);
	smpl[smpnum] = l;
	smpr[smpnum] = r;
	smpnum++;
}

void usesmp(int l, int r,int index) {
	cntn = cnt[index];
	cctn = cct[index];
	ln = smpl[index];
	rn = smpr[index];
	move(l, r);
	smpl[index] = ln;
	smpr[index] = rn;
}

int main()
{
	MSET(0, cnt);
	MSET(0, cct);
	read(n);
	read(m);
	read(type);
	REPI(n) read(a[i + 1]);
	ln = 1;
	rn = 0;
	cntn = cnt[0];
	cctn = cct[0];
	int lastans = 0;
	REPI(m) {
		read(l);
		read(r);
		read(k);
		if (type == 1) {
			l ^= lastans;
			r ^= lastans;
			k ^= lastans;
		}
		int cost = r - l + 1;
		if (smpnum == maxl) cost = INT_MAX;
		int index = -1;
		REPI(smpnum) {
			int ncost = abs(smpl[i] - l) + abs(smpr[i] - r);
			if (ncost < cost) {
				cost = ncost;
				index = i;
			}
		}
		if (index == -1) {
			setsmp(l, r);
		}
		else {
			usesmp(l, r, index);
		}
		int sum = r - l + 1;
		int now = 0;
		while (sum > 0) {
			now++;
			sum -= cctn[now] * now;
		}
		while (now > 0) {
			k -= cctn[now];
			if (k <= 0) break;
			now--;
		}
		lastans = now;
		printf("%d\n", lastans);
	}
}

上一题