QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#291045#4845. DFSRadewoosh#ML 7ms57128kbC++177.3kb2023-12-26 04:35:352023-12-26 04:35:36

Judging History

This is the latest submission verdict.

  • [2023-12-26 04:35:36]
  • Judged
  • Verdict: ML
  • Time: 7ms
  • Memory: 57128kb
  • [2023-12-26 04:35:35]
  • Submitted

answer

//~ while (clock()<=69*CLOCKS_PER_SEC)
//~ #pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("O3")
//~ #pragma GCC target ("avx2")
//~ #pragma GCC optimize("Ofast")
//~ #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//~ #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;

template <typename T>
using ordered_set =
    tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
    *this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "

#define shandom_ruffle random_shuffle

using ll=long long;
using pii=pair<int,int>;
using pll=pair<ll,ll>;
using vi=vector<int>;
using vll=vector<ll>;
const int nax=1000*1007;
const ll mod=998244353;

ll inv(ll v)
{
	if (v<=1)
		return v;
	return inv(mod%v)*(mod-mod/v)%mod;
}

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

struct node {
	int roz=1;
	int wag;
	int praw;
	int mnopra=1;
	int sumpra;
	int sumwag;
	node *lew, *oj, *pra;
	node() { lew=pra=oj=NULL; }
};
void update(node *v) {
	if (v==NULL) return;
	v->roz=1;
	v->sumpra=0;
	v->sumwag=0;
	for (int h=0; h<2; h++) {
		if (v->lew!=NULL) {
			v->roz+=v->lew->roz;
			(v->lew->mnopra)=(v->lew->mnopra)*(ll)(v->mnopra)%mod;
			(v->sumpra)=((v->sumpra)+(v->lew->sumpra)*(ll)(v->lew->mnopra))%mod;
			(v->sumwag)=((v->sumwag)+(v->lew->sumwag)*(ll)(v->lew->mnopra))%mod;
		}
		swap(v->lew, v->pra);
	}
	(v->praw)=(v->praw)*(ll)(v->mnopra)%mod;
	v->mnopra=1;
	(v->sumpra)=((v->sumpra)+(v->praw))%mod;
	(v->sumwag)=((v->sumwag)+(v->praw)*(ll)(v->wag))%mod;
}
node *merge(node *v, node *u) {
	if (v==NULL) return u;
	if (u==NULL) return v;	
	if (rng()%(v->roz+u->roz)<(v->roz)) {
		update(v);//czasem można usunąć
		v->pra=merge(v->pra, u);
		v->pra->oj=v;
		update(v);
		return v;
	} else {
		update(u);//czasem można usunąć
		u->lew=merge(v, u->lew);
		u->lew->oj=u;
		update(u);
		return u;
	}
}
pair <node*, node*> split(node *v, const function <bool(node*)> &is_left) {
	if (v==NULL)
		return make_pair(v, v);
	pair <node*, node*> ret;
	update(v);//czasem można usunąć
	v->oj=NULL;
	if (is_left(v)) {
		ret=split(v->pra, is_left);
		v->pra=ret.first;
		if (v->pra!=NULL)
			v->pra->oj=v;
		ret.first=v;
	} else {
		ret=split(v->lew, is_left);
		v->lew=ret.second;
		if (v->lew!=NULL)
			v->lew->oj=v;
		ret.second=v;
	}
	update(v);
	return ret;
}
ll gl_help;
function <bool(node*)> cut_v(int v) {
	gl_help=v;
	return [](node *u)->bool {
		int pom=1;
		if (u->lew!=NULL) pom+=u->lew->roz;
		if (pom>gl_help) return false;
		gl_help-=pom;
		return true;
	};
}
function <bool(node*)> cut_leq(ll v) {
	gl_help=v;
	return [](node *u)->bool {
		return (u->wag)<=gl_help;
	};
}
int position(node *v) {
	int ret=1;
	if (v->lew!=NULL) ret+=v->lew->roz;
	if (v->oj==NULL) return ret;
	return position(v->oj)+ret-(v->oj->lew==v)*(v->roz+1);
}

ll daj_sumpra(node *v)
{
	update(v);
	if (!v)
		return 0;
	return v->sumpra;
}

ll daj_sumwag(node *v)
{
	update(v);
	if (!v)
		return 0;
	return v->sumwag;
}

ll minimum(node *v)
{
	if (v->lew)
		return minimum(v->lew);
	return v->wag;
}

void przemnoz(node *v, ll w)
{
	if (!v)
		return;
	(v->mnopra)=(v->mnopra)*w%mod;
}

int n, korz;

ll tab[nax];

vi graf[nax];

ll minipod[nax];
node *dp[nax];

vector<pair<node*,int>> ciete[nax];
vll granice;

ll wyn;

void wypisz(node *v)
{
	if (!v)
		return;
	update(v);
	wypisz(v->lew);
	debug() << (v->wag) << " " << (v->praw);
	wypisz(v->pra);
}

void usun(node *v)
{
	if (!v)
		return;
	usun(v->lew);
	usun(v->pra);
	delete v;
}

bool mniej(int a, int b)
{
	return minipod[a]<minipod[b];
}

ll sumsuf[nax];

node *merge_smart(node *a, node *b)
{
	node *ret=NULL;
	while(a && b)
	{
		ll ma=minimum(a);
		ll mb=minimum(b);
		if (ma>mb)
		{
			swap(a, b);
			swap(ma, mb);
		}
		auto wez=split(a, cut_leq(mb));
		ret=merge(ret, wez.first);
		a=wez.second;
	}
	if (a)
		ret=merge(ret, a);
	if (b)
		ret=merge(ret, b);
	return ret;
}

void potnij(node *v, vector<pair<node*,int>> &wek)
{
	while(v)
	{
		ll x=minimum(v);
		int g=lower_bound(granice.begin(), granice.end(), x)-granice.begin();
		if (g==(int)granice.size())
		{
			wek.push_back({v, g});
			continue;
		}
		auto wez=split(v, cut_leq(granice[g]));
		wek.push_back({wez.first, g});
		v=wez.second;
	}
	for (int i=1; i<(int)wek.size(); i++)
		assert(wek[i].second!=wek[i-1].second);
}

void dfs1(int v, int oj)
{
	for (int &i : graf[v])
	{
		if (i==oj)
		{
			swap(i, graf[v].back());
			graf[v].pop_back();
			break;
		}
	}
	minipod[v]=tab[v];
	for (int i : graf[v])
	{
		dfs1(i, v);
		minipod[v]=min(minipod[v], minipod[i]);
	}
	sort(graf[v].begin(), graf[v].end(), mniej);
	granice.clear();
	for (int i : graf[v])
		granice.push_back(minipod[i]);
	for (int i : graf[v])
	{
		ciete[i].clear();
		potnij(dp[i], ciete[i]);
	}
	node *dod=NULL;
	int r=graf[v].size();
	for (int i=0; i<=r; i++)
		sumsuf[i]=0;
	for (int i : graf[v])
		for (auto j : ciete[i])
			sumsuf[j.second]+=daj_sumpra(j.first);
	for (int i=r-1; i>=0; i--)
		sumsuf[i]+=sumsuf[i+1];
	for (int i=0; i<=r; i++)
		sumsuf[i]%=mod;
	for (int i=0; i<r; i++)
	{
		ll x=sumsuf[i+1];
		for (auto j : ciete[graf[v][i]])
			if (j.second>i)
				x-=daj_sumpra(j.first);
		x%=mod;
		x+=mod;
		x%=mod;
		x=(x*inv(i+2))%mod;
		node *now=new node();
		now->wag=granice[i];
		now->praw=x;
		update(now);
		dod=merge(dod, now);
	}
	for (int i=0; i<r; i++)
	{
		for (auto j : ciete[graf[v][i]])
		{
			int mni=j.second;
			if (i<mni)
				mni--;
			przemnoz(j.first, inv(mni+1));
		}
	}
	for (int i : graf[v])
		for (auto j : ciete[i])
			dod=merge_smart(dod, j.first);
	
	auto wez=split(dod, cut_leq(tab[v]));
	node *now=new node();
	now->wag=tab[v];
	now->praw=daj_sumpra(wez.second)+1;
	update(now);
	usun(wez.second);
	dp[v]=merge(wez.first, now);
	
	wyn=(wyn+daj_sumwag(dp[v]))%mod;
}

void test()
{
	scanf("%d%d", &n, &korz);
	for (int i=1; i<=n; i++)
		scanf("%lld", &tab[i]);
	for (int i=1; i<=n; i++)
		graf[i].clear();
	for (int i=1; i<n; i++)
	{
		int a, b;
		scanf("%d%d", &a, &b);
		graf[a].push_back(b);
		graf[b].push_back(a);
	}
	wyn=0;
	dfs1(korz, 0);
	usun(dp[korz]);
	printf("%lld\n", wyn);
}

int main()
{
	int t;
	scanf("%d", &t);
	while(t--)
		test();
	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 7ms
memory: 57128kb

input:

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

output:

1
16
34
499122202

result:

ok 4 number(s): "1 16 34 499122202"

Test #2:

score: -100
Memory Limit Exceeded

input:

7
5000 933
23306350 162661794 68618194 666430282 995855733 929210414 295740530 464135554 304211641 725090719 226242817 592655639 936895997 479520010 108891341 598601399 678169271 118406229 394867734 640888099 481066130 606481085 709600400 554804145 179044332 41718098 549318629 400214219 159098456 67...

output:


result: