QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#125971#5425. Proposition CompositionsavacskaTL 225ms57328kbC++237.3kb2023-07-18 06:07:202023-07-18 06:07:23

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-07-18 06:07:23]
  • 评测
  • 测评结果:TL
  • 用时:225ms
  • 内存:57328kb
  • [2023-07-18 06:07:20]
  • 提交

answer

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define pb push_back
#define mp make_pair
#define x first
#define y second

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef tree<int, null_type, less <int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

const int INF = (int) 1e9;

struct PokrNode
{
	int min, cnt;
	int upd;
};

pair <int, int> edge[250005];
PokrNode tree_pokr[1000005];
int tree_sosed[1000005];
set <pair <int, int> > strong;
int svyaz[250005];
ordered_set opa[600005];
int quant = 0;

void full_pokr(int v, int lef, int rig, int val)
{
 	tree_pokr[v].min += val;
 	tree_pokr[v].upd += val;
 	return;
}

void push_pokr(int v, int lef, int rig)
{
 	int mid = (lef + rig) / 2;
 	full_pokr(2 * v, lef, mid, tree_pokr[v].upd);
 	full_pokr(2 * v + 1, mid + 1, rig, tree_pokr[v].upd);
 	tree_pokr[v].upd = 0;
 	return;
}

void build_pokr(int v, int lef, int rig)
{
	if (lef == rig) {tree_pokr[v] = {INF, 1, 0}; return;}
	int mid = (lef + rig) / 2;
	build_pokr(2 * v, lef, mid);
	build_pokr(2 * v + 1, mid + 1, rig);
	tree_pokr[v] = {INF, rig - lef + 1, 0};
	return; 	
}

void update_pokr(int v, int lef, int rig, int A, int B, int val)
{
 	if (lef > B || rig < A) return;
 	if (A <= lef && rig <= B)
 	{
 	 	full_pokr(v, lef, rig, val);
 	 	return;
 	}
 	push_pokr(v, lef, rig);
 	int mid = (lef + rig) / 2;
 	update_pokr(2 * v, lef, mid, A, B, val);
 	update_pokr(2 * v + 1, mid + 1, rig, A, B, val);

 	tree_pokr[v].min = tree_pokr[2 * v].min, tree_pokr[v].cnt = tree_pokr[2 * v].cnt;
 	if (tree_pokr[2 * v + 1].min < tree_pokr[v].min) tree_pokr[v].min = tree_pokr[2 * v + 1].min, tree_pokr[v].cnt = tree_pokr[2 * v + 1].cnt;
 	else if (tree_pokr[2 * v + 1].min == tree_pokr[v].min) tree_pokr[v].cnt += tree_pokr[2 * v + 1].cnt;
 	return;
}

void update_pokr_point(int v, int lef, int rig, int pos, int val)
{
 	if (lef == rig) {tree_pokr[v] = {val, 1, 0}; return;}
 	push_pokr(v, lef, rig);
 	int mid = (lef + rig) / 2;
 	if (pos <= mid) update_pokr_point(2 * v, lef, mid, pos, val);
 	else update_pokr_point(2 * v + 1, mid + 1, rig, pos, val);

 	tree_pokr[v].min = tree_pokr[2 * v].min, tree_pokr[v].cnt = tree_pokr[2 * v].cnt;
 	if (tree_pokr[2 * v + 1].min < tree_pokr[v].min) tree_pokr[v].min = tree_pokr[2 * v + 1].min, tree_pokr[v].cnt = tree_pokr[2 * v + 1].cnt;
 	else if (tree_pokr[2 * v + 1].min == tree_pokr[v].min) tree_pokr[v].cnt += tree_pokr[2 * v + 1].cnt;
 	return;
}

void build_sosed(int v, int lef, int rig)
{
 	if (lef == rig) {tree_sosed[v] = 0; return;}
 	int mid = (lef + rig) / 2;
 	build_sosed(2 * v, lef, mid);
 	build_sosed(2 * v + 1, mid + 1, rig);
 	tree_sosed[v] = 0;
 	return;
}

void dfsik_sosed(int v, int lef, int rig, int bound, int A, int B, vector <int> &spis)
{
 	if (tree_sosed[v] > bound) return;
 	if (lef > B || rig < A) return;
 	if (lef == rig) {spis.pb(lef); return;}
 	int mid = (lef + rig) / 2;
 	dfsik_sosed(2 * v, lef, mid, bound, A, B, spis);
 	dfsik_sosed(2 * v + 1, mid + 1, rig, bound, A, B, spis);
 	return;
}

void update_sosed(int v, int lef, int rig, int pos, int val)
{
 	if (lef == rig) {tree_sosed[v] = val; return;}
 	int mid = (lef + rig) / 2;
 	if (pos <= mid) update_sosed(2 * v, lef, mid, pos, val);
 	else update_sosed(2 * v + 1, mid + 1, rig, pos, val);
 	tree_sosed[v] = min(tree_sosed[2 * v], tree_sosed[2 * v + 1]);
 	return;
}

void cut(int start, int lef, int rig, ll &sum_sizes, int n)
{
	//cout << "Cut: " << start << '\n';
	//for (int x : opa[svyaz[start]]) cout << x << ' ';
	//cout << "--------------\n";

	int num = svyaz[start];
	int sz = (int) opa[num].size();
	int kol = opa[num].order_of_key(rig) - opa[num].order_of_key(lef);
 	if (kol == sz) return;
 	
 	sum_sizes -= (ll) sz * (sz - 1) / 2;
 	//cout << "Cut2: " << start << '\n';
 	quant++;
 	opa[quant].clear();
 	sum_sizes += (ll) kol * (kol - 1) / 2;
 	sum_sizes += (ll) (sz - kol) * (sz - kol - 1) / 2;

 	auto it1 = opa[num].find(start);
 	auto it2 = opa[num].lower_bound(rig);
 	int pr = (it1 == opa[num].begin()) ? 0 : *prev(it1);
 	int nx = (it2 == opa[num].end()) ? n : *it2;
 	if (2 * kol >= sz)
 	{
 		for (auto it = opa[num].begin(); *it != start; it++)
 			opa[quant].insert(*it);
 	 	for (auto it = opa[num].lower_bound(rig); it != opa[num].end(); it++)
 	 		opa[quant].insert(*it);
 	}
 	else
 	{
 		auto startIt = opa[num].find(start);
 		auto finishIt = opa[num].lower_bound(rig);
 		for (auto it = startIt; it != finishIt; it++)
 			opa[quant].insert(*it);
 	}
 	update_sosed(1, 1, n - 1, start, 0);
 	if (nx != n) update_sosed(1, 1, n - 1, nx, pr);	
 	for (int x : opa[quant])
 	{
 	 	svyaz[x] = quant;
 	 	opa[num].erase(x);
 	}
 	return;
}

int main()
{
 	//freopen("input.txt", "r", stdin);
 	//freopen("output.txt", "w", stdout);
 	ios_base::sync_with_stdio(0); cin.tie(0);

 	int test;
 	cin >> test;
 	for (int rep = 1; rep <= test; rep++)
 	{
 	 	int n, m;
 	 	cin >> n >> m;
 	 	for (int i = 1; i <= m; i++)
 	 	{
 	 		cin >> edge[i].x >> edge[i].y;
 	 		if (edge[i].x > edge[i].y) swap(edge[i].x, edge[i].y); 	
 	 	}

 	 	if (n == 1)
 	 	{
 	 	 	for (int i = 1; i <= m; i++) cout << "0\n";
 	 	 	continue;
 	 	}

 	 	int all_edges = n - 1, bridges = n - 1;
 	 	ll sum_sizes = 0;
 	 	
 	 	strong.clear();
 	 	for (int i = 1; i <= n; i++) strong.insert(mp(i, i));

 	 	quant = 0;

 	 	build_pokr(1, 1, n - 1);
 	 	build_sosed(1, 1, n - 1);

 	 	for (int i = 1; i <= m; i++)
 	 	{
 	 	 	int lef = edge[i].x, rig = edge[i].y;
 	 	 	all_edges++;
 	 	 	
 	 	 	if (lef != rig)
 	 	 	{
 	 	 		auto itlef = strong.lower_bound(mp(lef + 1, 0));
 	 	 		itlef--;
 	 	 		auto itrig = strong.lower_bound(mp(rig + 1, 0));

 	 	 		vector <pair <int, int> > spis;
 	 	 		for (auto it = itlef; it != itrig; it++)
 	 	 			spis.pb(*it);
 	 	 		if ((int) spis.size() != 1)
 	 	 		{
 	 	 			quant++;
 	 	 			opa[quant].clear();
 	 	 		}
 	 	 		for (int i = 1; i < (int) spis.size(); i++)
 	 	 		{
 	 	 			update_pokr_point(1, 1, n - 1, spis[i - 1].y, 0);
 	 	 			opa[quant].insert(spis[i - 1].y);
 	 	 			svyaz[spis[i - 1].y] = quant;
 	 	 			bridges--;
 	 	 		}
 	 	 		update_pokr(1, 1, n - 1, lef, rig - 1, 1);
 	 	 		if ((int) spis.size() != 1)
 	 	 		{
 	 	 		 	int last = 0;
 	 	 		 	for (int x : opa[quant])
 	 	 		 	{
 	 	 		 	 	update_sosed(1, 1, n - 1, x, last);
 	 	 		 	 	last = x;
 	 	 		 	}
 	 	 		 	sum_sizes += (ll) opa[quant].size() * ((ll) opa[quant].size() - 1) / 2;
 	 	 		}

 	 	 		int resL = spis[0].x, resR = spis.back().y;
 	 	 		for (int i = 0; i < (int) spis.size(); i++) strong.erase(spis[i]);
 	 	 		strong.insert(mp(resL, resR));

 	 	 		vector <int> starts;
 	 	 		dfsik_sosed(1, 1, n - 1, lef - 1, lef, rig - 1, starts);

 	 	 		for (int start : starts) cut(start, lef, rig, sum_sizes, n);
 	 	 	}

 	 	 	ll ans = (ll) bridges * (bridges - 1) / 2 + (ll) bridges * (all_edges - bridges);
 	 	 	int mn = tree_pokr[1].min, cnt = tree_pokr[1].cnt;
 	 	 	if (mn == 1) ans += cnt;
 	 	 	ans += sum_sizes;
 	 	 	//cout << all_edges << ' ' << bridges << ' ' << mn << ' ' << cnt << ' ' << sum_sizes << '\n';
 	 	 	cout << ans << '\n';
        }
 	}

 	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 22ms
memory: 57328kb

input:

3
4 3
2 4
4 2
3 3
7 3
3 4
1 2
1 7
6 4
1 3
4 6
2 5
3 4

output:

6
5
6
21
24
10
15
12
3
2

result:

ok 10 numbers

Test #2:

score: 0
Accepted
time: 108ms
memory: 55516kb

input:

45540
10 9
10 1
1 10
10 1
1 10
1 10
10 1
1 10
3 3
10 1
10 4
1 2
1 10
3 4
1 10
7 6
7 1
5 6
1 7
6 6
7 1
6 7
9 7
3 3
7 7
5 4
1 1
9 1
9 1
6 5
8 7
1 8
4 4
5 6
1 1
1 8
6 6
4 5
3 3
3 2
3 1
3 3
3 9
3 1
3 3
2 2
3 3
3 1
2 2
1 1
2 3
3 1
10 1
2 1
7 1
1 7
3 8
1 3
1 3
3 3
1 3
2 2
1 3
1 3
3 3
3 6
3 1
1 3
1 3
1 3
1...

output:

45
36
36
36
36
36
36
36
36
45
36
28
21
21
15
10
10
10
6
36
44
50
57
28
21
15
28
28
21
21
15
15
10
3
1
1
3
3
3
3
1
1
1
0
0
45
21
3
1
1
1
1
1
1
1
3
1
1
1
1
1
45
36
36
36
36
36
36
36
3
3
1
0
0
0
0
0
0
3
1
0
0
15
10
10
0
0
0
0
0
0
0
0
28
34
21
6
6
6
6
1
0
0
21
15
15
0
0
0
0
0
0
0
45
53
0
0
0
0
0
0
0
0
1...

result:

ok 249586 numbers

Test #3:

score: 0
Accepted
time: 225ms
memory: 56976kb

input:

2507
86 4
41 41
36 36
31 30
86 1
110 22
1 110
110 1
11 11
110 1
110 1
110 1
1 110
107 106
72 72
106 106
74 74
1 110
110 1
58 58
110 1
110 1
1 110
101 100
110 1
100 100
110 1
8 7
114 180
114 1
114 1
114 1
1 114
1 114
114 1
37 38
49 48
105 106
1 114
90 90
1 114
9 9
114 1
67 68
20 20
114 1
1 114
54 55
...

output:

3655
3740
3823
3570
5995
5886
5886
5886
5886
5886
5886
5778
5778
5778
5778
5778
5778
5778
5778
5778
5778
5671
5671
5671
5671
5565
6441
6328
6328
6328
6328
6328
6216
6105
5995
5995
5995
5995
5995
5995
5886
5886
5886
5886
5778
5671
5671
5565
5565
5460
5460
5460
5460
5460
5356
5253
5253
5253
5151
5151
...

result:

ok 249877 numbers

Test #4:

score: -100
Time Limit Exceeded

input:

3
82425 27858
30801 30802
1 82425
73850 73850
1 82425
65949 65949
82425 1
76026 76025
61936 61936
82425 1
82425 1
82425 1
6504 6504
82425 1
25155 25156
79743 79743
1 82425
69406 69406
29247 29247
18351 18351
23171 23170
29704 29703
82425 1
1 82425
82425 1
74918 74917
22395 22394
893 894
82425 1
391 ...

output:

3396899100
3396816676
3396816676
3396734253
3396734253
3396734253
3396651831
3396651831
3396651831
3396651831
3396651831
3396651831
3396651831
3396569410
3396569410
3396569410
3396569410
3396569410
3396569410
3396486990
3396404571
3396404571
3396404571
3396404571
3396322153
3396239736
3396157320
339...

result: