ABC298解题报告

比赛传送门

C. Cards Query Problem

题意:有一些盒子,每次操作有以下三种:把数 \(i\) 扔到集合 \(j\) 内;查询某个集合里的所有数(升序)(可重);查询包含某个数的集合(升序)(去重)。保证输出的数个数在 \(2\times 10^5\) 内。

可以维护两个 map 套 set,分别表示盒子的数和数的盒子,其中盒子的数用 multiset,数的盒子用 set。每次插入就同时往两个桶里扔,查询就输出一个桶即可。

By cxm1024

#include <bits/stdc++.h>
using namespace std;
signed main() {
	int n, q;
	scanf("%d%d", &n, &q);
	map<int, multiset<int> > mp1;
	map<int, set<int> > mp2;
	while (q--) {
		int op, x, y;
		scanf("%d%d", &op, &x);
		if (op == 1) {
			scanf("%d", &y);
			mp1[y].insert(x), mp2[x].insert(y);
		}
		else if (op == 2) {
			for (int tmp : mp1[x])
				printf("%d ", tmp);
			puts("");
		}
		else {
			for (int tmp : mp2[x])
				printf("%d ", tmp);
			puts("");
		}
	}
	return 0;
}

同样可以使用 map 套 vector,每次输出时暴力排序(可能去重)后输出。因为输出总数的限制,所以复杂度不会有问题。

By noimi

int main() {
    INT(n, q);
    constexpr int N = 200001;
    vector<vi> a(N), b(N);

    rep(q) {
        INT(t);
        if(t == 1) {
            INT(i, j);
            a[j].eb(i);
            b[i].eb(j);
        } else if(t == 2) {
            INT(i);
            SORT(a[i]);
            OUT(a[i]);
        } else {
            INT(i);
            UNIQUE(b[i]);
            OUT(b[i]);
        }
    }
}

也可以使用堆维护,本质相同。

By pengin

#include<stdio.h>
int cnt_box[400005], sum_cnt_box[400005];
int cnt_card[400005], sum_cnt_card[400005];
int h_box[400005], l_box[200005];
int h_card[400005], l_card[200005];
int comp_h_box(int a, int b)
{
	if (h_box[a] > h_box[b])
		return 1;
	else
		return -1;
}
int comp_h_card(int a, int b)
{
	if (h_card[a] > h_card[b])
		return 1;
	else
		return -1;
}
void swap_h_box(int a, int b)
{
	int f = h_box[a];
	h_box[a] = h_box[b];
	h_box[b] = f;
	return;
}
void swap_h_card(int a, int b)
{
	int f = h_card[a];
	h_card[a] = h_card[b];
	h_card[b] = f;
	return;
}
void push_box(int box, int ne)
{
	h_box[l_box[box]] = ne;
	int p = l_box[box];
	l_box[box]++;
	for (; p > sum_cnt_box[box]; p = (p - sum_cnt_box[box] - 1) / 2 + sum_cnt_box[box])
		if (comp_h_box((p - sum_cnt_box[box] - 1) / 2 + sum_cnt_box[box], p) > 0)
			swap_h_box((p - sum_cnt_box[box] - 1) / 2 + sum_cnt_box[box], p);
	return;
}
void push_card(int card, int ne)
{
	h_card[l_card[card]] = ne;
	int p = l_card[card];
	l_card[card]++;
	for (; p > sum_cnt_card[card]; p = (p - sum_cnt_card[card] - 1) / 2 + sum_cnt_card[card])
		if (comp_h_card((p - sum_cnt_card[card] - 1) / 2 + sum_cnt_card[card], p) > 0)
			swap_h_card((p - sum_cnt_card[card] - 1) / 2 + sum_cnt_card[card], p);
	return;
}
int pop_box(int box)
{
	l_box[box]--;
	swap_h_box(sum_cnt_box[box], l_box[box]);
	int p = sum_cnt_box[box];
	for (;;)
	{
		if (2 * (p - sum_cnt_box[box]) + 2 + sum_cnt_box[box] < l_box[box])
		{
			if (comp_h_box(2 * (p - sum_cnt_box[box]) + 1 + sum_cnt_box[box], 2 * (p - sum_cnt_box[box]) + 2 + sum_cnt_box[box]) > 0)
			{
				if (comp_h_box(p, 2 * (p - sum_cnt_box[box]) + 2 + sum_cnt_box[box]) > 0)
					swap_h_box(p, 2 * (p - sum_cnt_box[box]) + 2 + sum_cnt_box[box]);
				p = 2 * (p - sum_cnt_box[box]) + 2 + sum_cnt_box[box];
			}
			else
			{
				if (comp_h_box(p, 2 * (p - sum_cnt_box[box]) + 1 + sum_cnt_box[box]) > 0)
					swap_h_box(p, 2 * (p - sum_cnt_box[box]) + 1 + sum_cnt_box[box]);
				p = 2 * (p - sum_cnt_box[box]) + 1 + sum_cnt_box[box];
			}
		}
		else if (2 * (p - sum_cnt_box[box]) + 1 + sum_cnt_box[box] < l_box[box])
		{
			if (comp_h_box(p, 2 * (p - sum_cnt_box[box]) + 1 + sum_cnt_box[box]) > 0)
				swap_h_box(p, 2 * (p - sum_cnt_box[box]) + 1 + sum_cnt_box[box]);
			p = 2 * (p - sum_cnt_box[box]) + 1 + sum_cnt_box[box];
		}
		else
			break;
	}
	return h_box[l_box[box]];
}
int pop_card(int card)
{
	l_card[card]--;
	swap_h_card(sum_cnt_card[card], l_card[card]);
	int p = sum_cnt_card[card];
	for (;;)
	{
		if (2 * (p - sum_cnt_card[card]) + 2 + sum_cnt_card[card] < l_card[card])
		{
			if (comp_h_card(2 * (p - sum_cnt_card[card]) + 1 + sum_cnt_card[card], 2 * (p - sum_cnt_card[card]) + 2 + sum_cnt_card[card]) > 0)
			{
				if (comp_h_card(p, 2 * (p - sum_cnt_card[card]) + 2 + sum_cnt_card[card]) > 0)
					swap_h_card(p, 2 * (p - sum_cnt_card[card]) + 2 + sum_cnt_card[card]);
				p = 2 * (p - sum_cnt_card[card]) + 2 + sum_cnt_card[card];
			}
			else
			{
				if (comp_h_card(p, 2 * (p - sum_cnt_card[card]) + 1 + sum_cnt_card[card]) > 0)
					swap_h_card(p, 2 * (p - sum_cnt_card[card]) + 1 + sum_cnt_card[card]);
				p = 2 * (p - sum_cnt_card[card]) + 1 + sum_cnt_card[card];
			}
		}
		else if (2 * (p - sum_cnt_card[card]) + 1 + sum_cnt_card[card] < l_card[card])
		{
			if (comp_h_card(p, 2 * (p - sum_cnt_card[card]) + 1 + sum_cnt_card[card]) > 0)
				swap_h_card(p, 2 * (p - sum_cnt_card[card]) + 1 + sum_cnt_card[card]);
			p = 2 * (p - sum_cnt_card[card]) + 1 + sum_cnt_card[card];
		}
		else
			break;
	}
	return h_card[l_card[card]];
}
int T[200005], I[200005], J[200005];
int hoge[200005], fuga;
int main()
{
	int n, q;
	scanf("%d%d", &n, &q);
	int i, j, k;
	for (k = 0; k < q; k++)
	{
		scanf("%d %d", &T[k], &I[k]);
		I[k]--;
		if (T[k] == 1)
		{
			scanf("%d", &J[k]);
			J[k]--;
		}
	}
	for (i = 0; i < n; i++)
		cnt_box[i] = 0;
	for (k = 0; k < q; k++)
		if (T[k] == 1)
			cnt_box[J[k]]++;
	sum_cnt_box[0] = 0;
	for (i = 0; i < n; i++)
		sum_cnt_box[i + 1] = sum_cnt_box[i] + cnt_box[i];
	for (i = 0; i < 200005; i++)
		cnt_card[i] = 0;
	for (k = 0; k < q; k++)
		if (T[k] == 1)
			cnt_card[I[k]]++;
	sum_cnt_card[0] = 0;
	for (i = 0; i < 400000; i++)
		sum_cnt_card[i + 1] = sum_cnt_card[i] + cnt_card[i];
	for (i = 0; i < n; i++)
		l_box[i] = sum_cnt_box[i];
	for (i = 0; i < 200005; i++)
		l_card[i] = sum_cnt_card[i];
	for (k = 0; k < q; k++)
	{
		if (T[k] == 1)
		{
			push_box(J[k], I[k]);
			push_card(I[k], J[k]);
		}
		else if (T[k] == 2)
		{
			fuga = 0;
			while (l_box[I[k]] > sum_cnt_box[I[k]])
			{
				hoge[fuga] = pop_box(I[k]);
				fuga++;
			}
			for (i = 0; i < fuga - 1; i++)
				printf("%d ", hoge[i] + 1);
			printf("%d\n", hoge[fuga - 1] + 1);
			for (i = 0; i < fuga; i++)
				push_box(I[k], hoge[i]);
		}
		else
		{
			fuga = 0;
			while (l_card[I[k]] > sum_cnt_card[I[k]])
			{
				hoge[fuga] = pop_card(I[k]);
				fuga++;
			}
			printf("%d", hoge[0] + 1);
			for (i = 1; i < fuga; i++)
			{
				if (hoge[i] == hoge[i - 1])
					continue;
				printf(" %d", hoge[i] + 1);
			}
			printf("\n");
			push_card(I[k], hoge[0]);
			for (i = 1; i < fuga; i++)
			{
				if (hoge[i] == hoge[i - 1])
					continue;
				push_card(I[k], hoge[i]);
			}
		}
	}
	return 0;
}

一个错解:

By daisybunny

#include<bits/stdc++.h>
using namespace std;
int n,q;
vector<int> v[200005];
vector<int> v2[200005];
int main()
{
	cin>>n>>q;
	while(q--)
	{
		int x,i,j;
		cin>>x>>i;
		if(x==1)
		{
			cin>>j;
			j--;
			v2[i].push_back(j);
			v[j].push_back(i);
		}
		else if(x==2)
		{
			i--;
			sort(v[i].begin(),v[i].end());
			for(int t=0;t<v[i].size();t++)
			{
				cout<<v[i][t]<<" ";
			}
			cout<<endl;
		}
		else
		{
			sort(v2[i].begin(),v2[i].end());
			cout<<v2[i][0]+1<<" ";
			for(int t=1;t<v2[i].size();t++)
			{
				if(v2[i][t]!=v2[i][t-1])
				{
					cout<<v2[i][t]+1<<" ";
				}
			}
			cout<<endl;
		}
	}
	return 0;
}

这个做法也是每次排序去重输出,但他并没有真的去重,导致集合里可能会有非常多重复元素,每次都要扫一遍但不输出。然而,题目只规定了输出的大小之和,并没有规定集合的元素个数和,而此时后者可能会比前者大得多,于是会超时。

Hack:

200000 200000
1 1 1
1 1 1
...
1 1 1 (100000 times)
3 1
3 1
...
3 1 (100000 times)
posted @ 2023-04-15 22:54  曹轩鸣  阅读(51)  评论(0编辑  收藏  举报