Codeforces Round #756 (Div. 3)

比赛链接

Codeforces Round #756 (Div. 3)

E2. Escape The Maze (hard version)

Vlad built a maze out of \(n\) rooms and \(n-1\) bidirectional corridors. From any room \(u\) any other room \(v\) can be reached through a sequence of corridors. Thus, the room system forms an undirected tree.
Vlad invited \(k\) friends to play a game with them.
Vlad starts the game in the room 1 and wins if he reaches a room other than 1 , into which exactly one corridor leads. Friends are placed in the maze: the friend with number \(i\) is in the room \(x_{i}\), and no two friends are in the same room (that is, \(x_{i} \neq x_{j}\) for all \(i \neq j\) ). Friends win if one of them meets Vlad in any room or corridor before he wins.

For one unit of time, each participant of the game can go through one corridor. All participants move at the same time. Participants may not move. Each room can fit all participants at the same time.

Friends know the plan of a maze and intend to win. They don't want to waste too much energy. They ask you to determine if they can win and if they can, what minimum number of friends must remain in the maze so that they can always catch Vlad.

In other words, you need to determine the size of the minimum (by the number of elements) subset of friends who can catch Vlad or say that such a subset does not exist.

Input

The first line of the input contains an integer \(t\left(1 \leq t \leq 10^{4}\right)\) - the number of test cases in the input. The input contains an empty string before each test case.

The first line of the test case contains two numbers \(n\) and \(k\left(1 \leq k<n \leq 2 \cdot 10^{5}\right)\) - the number of rooms and friends, respectively.
The next line of the test case contains \(k\) integers \(x_{1}, x_{2}, \ldots, x_{k}\left(2 \leq x_{i} \leq n\right)\) - numbers of rooms with friends. All \(x_{i}\) are different.
The next \(n-1\) lines contain descriptions of the corridors, two numbers per line \(v_{j}\) and \(u_{j}\left(1 \leq u_{j}, v_{j} \leq n\right)\) - numbers of rooms that connect the \(j\) corridor. All corridors are bidirectional. From any room, you can go to any other by moving along the corridors.
It is guaranteed that the sum of the values \(n\) over all test cases in the test is not greater than \(2 \cdot 10^{5}\).

Output

Print \(t\) lines, each line containing the answer to the corresponding test case. The answer to a test case should be \(-1\) if Vlad wins anyway and a minimal number of friends otherwise.

Example

input

4

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

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

3 1
2
1 2
2 3

3 2
2 3
3 1
1 2

output

-1
2
1
2

解题思路

dfs,倍增

如果存在某个节点上,则根节点到不了以节点为根的子树的任意一个叶子节点上,将当前所有存在的节点都向上走到极限位置上,即根节点向下走的同时能够与当前节点相遇的位置,即假设当前节点深度为 \(dep[i]\),根节点深度为 \(1\),则极限位置的深度为 \(dep[i]/2+1\),可以倍增求解,最后从根节点 \(dfs\) 一遍即可,即遇到极限位置则答案加一,否则如果到达叶子节点则答案为 \(-1\)

  • 时间复杂度:\(O(klogn+n)\)

代码

// Problem: E2. Escape The Maze (hard version)
// Contest: Codeforces - Codeforces Round #756 (Div. 3)
// URL: https://codeforces.com/contest/1611/problem/E2
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=2e5+5;
int t,n,k,dep[N],f[N][20],tt,a[N],res;
vector<int> adj[N];
bool v[N],ret;
void bfs()
{
	queue<int> q;
	q.push(1);
	dep[1]=1;
	while(q.size())
	{
		int x=q.front();
		q.pop();
		for(int y:adj[x])
		{
			if(!dep[y])
			{
				dep[y]=dep[x]+1;
				f[y][0]=x;
				for(int i=1;i<=tt;i++)f[y][i]=f[f[y][i-1]][i-1];
				q.push(y);
			}
		}
	}
}
void dfs(int x,int fa)
{
	if(v[x])
	{
		res++;
		return ;
	}
	if(x!=1&&adj[x].size()==1)
	{
		ret=true;
		return ;
	}
	for(int y:adj[x])
	{
		if(y==fa)continue;
		dfs(y,x);
	}
}
int main()
{
    help;
    for(cin>>t;t;t--)
    {
    	cin>>n>>k;
    	tt=log(n)/log(2);
		for(int i=1;i<=n;i++)adj[i].clear(),dep[i]=v[i]=0;
		for(int i=1;i<=k;i++)cin>>a[i],v[a[i]]=true;
		for(int i=1;i<n;i++)
		{
			int x,y;
			cin>>x>>y;
			adj[x].pb(y);
			adj[y].pb(x);
		}
		bfs();
		for(int i=1;i<=k;i++)
		{
			int x=a[i];
			int d=dep[x]/2+1;
			for(int j=tt;j>=0;j--)
				if(dep[f[x][j]]>=d)x=f[x][j],v[x]=true;
		} 
		res=ret=0;
		dfs(1,0);
		if(ret)
			puts("-1");
		else
			cout<<res<<'\n';
    }
    return 0;
}

F. ATM and Students

Polycarp started working at a bank. He was assigned to monitor the ATM. The ATM initially contains \(s\) rubles.
A queue of \(n\) students lined up to him. Each student wants to either withdraw a certain amount of money or deposit it into an account. If \(a_{i}\) is positive, then the student credits that amount of money via ATM. Otherwise, the student withdraws \(\left|a_{i}\right|\) rubles.

In the beginning, the ATM is turned off and an arbitrary number of students are not served. At some point, Polycarp turns on the ATM, which has an initial amount of \(s\) rubles. Then, the remaining students start queueing at the ATM. If at some point in time there is less money in the ATM than the student wants to withdraw, then the student is not served and Polycarp turns off the ATM and does not turn it on anymore.
More formally, the students that are served are forming a contiguous subsequence.
Polycarp wants the ATM to serve the maximum number of students. Help him in this matter. Print the numbers of the first and last student, or determine that he will not be able to serve anyone.

In other words, find such a longest continuous segment of students that, starting with the sum of \(s\) at the ATM, all these students will be served. ATM serves students consistently (i.e. one after another in the order of the queue).

Input

The first line of the input contains one integer \(t\left(1 \leq t \leq 10^{4}\right)\) - the number of test cases.
Each test case consists of two lines. The first one contains integers \(n\) and \(s\left(1 \leq n \leq 2 \cdot 10^{5} ; 0 \leq s \leq 10^{9}\right)-\) the length of the \(a\) array and the initial amount of rubles in the ATM. The second contains \(n\) integers \(a_{1}, a_{2}, \ldots, a_{n}\left(-10^{9} \leq a_{i} \leq 10^{9}\right)-\) elements of the \(a\) array. Note that \(a_{i}\) can be zero.
It is guaranteed that the sum of the values \(n\) over all test cases does not exceed \(2 \cdot 10^{5}\).

Output

Print \(t\) lines, each line must contain the answer to the corresponding set of input data: if the answer exists, print the numbers of the first and last served student. If there is no solution, then print \(-1\) on the line.
If there are several possible answers, print any.

Example

input

3
4 10
-16 2 -6 8
3 1000
-100000 -100000 -100000
6 0
2 6 -164 1 -1 -6543

output

2 4
-1
1 2

解题思路

分治

假设开始时权值为 \(x\),从 \(i\) 开始,到 \(j-1\) 结束,即 \(x+x_i+x_{i+1}+\dots + x_j<0\),即 \(x+s_j-s_{i-1}<0\),即 \(x-s_{i-1}<-s_j\),其中 \(j\)\(i\) 的右边第一个满足此不等式的下标,即要找 \(i\) 的左边第一个 \(-s_j\) 大于 \(x-s_{i-1}\)\(j\),其贡献为 \(j-i\),可用线段树求解,当然这里没有修改操作,直接转换为 \(倍增+分治\) 求解即可

  • 时间复杂度:\(O(nlogn)\)

代码

// Problem: F. ATM and Students
// Contest: Codeforces - Codeforces Round #756 (Div. 3)
// URL: https://codeforces.com/contest/1611/problem/F
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
// #define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=2e5+5;
int t,n,x,res[N];
LL a[N],s[N],b[N],f[N][20];
LL mx(int l,int r)
{
	int k=log(r-l+1)/log(2);
	return max(f[l][k],f[r-(1<<k)+1][k]);
}
int cal(LL x,int l,int r)
{
	if(mx(l,r)<=x)return -1;
	if(l==r)return l;
	int mid=l+r>>1;
	if(mx(l,mid)>x)return cal(x,l,mid);
	return cal(x,mid+1,r);
}
int main()
{
    help;
    for(cin>>t;t;t--)
    {
    	cin>>n>>x;
    	for(int i=1;i<=n;i++)cin>>a[i],s[i]=s[i-1]+a[i],f[i][0]=-s[i];
    	int t=log(n)/log(2);
    	for(int i=1;i<=t;i++)
    		for(int j=1;j+(1<<(i-1))<=n;j++)f[j][i]=max(f[j][i-1],f[j+(1<<(i-1))][i-1]);
    	int res=0,st=0,en=0;
    	for(int i=1;i<=n;i++)
    	{
    		int pos=cal(x-s[i-1],i,n);
    		if(pos==-1)
    		{
    			if(res<n-i+1)res=n-i+1,st=i,en=n;
    		}
    		else
    		{
    			if(res<pos-i)res=pos-i,st=i,en=pos-1;
    		}
    	}
    	if(res)cout<<st<<' '<<en<<'\n';
    	else
    		puts("-1");
    }
    return 0;
}
posted @ 2022-05-11 12:36  zyy2001  阅读(42)  评论(0编辑  收藏  举报