目录
D. Binary String To Subsequences
E1. Weights Division (easy version)
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given a binary string ss consisting of nn zeros and ones.
Your task is to divide the given string into the minimum number of subsequences in such a way that each character of the string belongs to exactly one subsequence and each subsequence looks like "010101 ..." or "101010 ..." (i.e. the subsequence should not contain two adjacent zeros or ones).
Recall that a subsequence is a sequence that can be derived from the given sequence by deleting zero or more elements without changing the order of the remaining elements. For example, subsequences of "1011101" are "0", "1", "11111", "0111", "101", "1001", but not "000", "101010" and "11100".
You have to answer tt independent test cases.
Input
The first line of the input contains one integer tt (1≤t≤2⋅1041≤t≤2⋅104) — the number of test cases. Then tt test cases follow.
The first line of the test case contains one integer nn (1≤n≤2⋅1051≤n≤2⋅105) — the length of ss. The second line of the test case contains nn characters '0' and '1' — the string ss.
It is guaranteed that the sum of nn does not exceed 2⋅1052⋅105 (∑n≤2⋅105∑n≤2⋅105).
Output
For each test case, print the answer: in the first line print one integer kk (1≤k≤n1≤k≤n) — the minimum number of subsequences you can divide the string ss to. In the second line print nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤k1≤ai≤k), where aiai is the number of subsequence the ii-th character of ss belongs to.
If there are several answers, you can print any.
Example
input
Copy
4
4
0011
6
111111
5
10101
8
01010000
output
Copy
2
1 2 2 1
6
1 2 3 4 5 6
1
1 1 1 1 1
4
1 1 1 1 1 2 3 4
思路:双队列模拟。末尾为1的子序列号保存在queue1,末尾为0的子序列号保存在queue0.遇到1从queue0中取,遇到0从queue1中取。
#include
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const int N = 2e5+10;
int ans[N];
char tem[N];
int main()
{
int t;
cin>>t;
while(t--)
{
queue q1;
queue q0;
int cnt = 0;
int n;
cin>>n;
string s;
cin>>s;
for(int i=0; i
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Easy and hard versions are actually different problems, so we advise you to read both statements carefully.
You are given a weighted rooted tree, vertex 11 is the root of this tree.
A tree is a connected graph without cycles. A rooted tree has a special vertex called the root. A parent of a vertex vv is the last different from vv vertex on the path from the root to the vertex vv. Children of vertex vv are all vertices for which vv is the parent. A vertex is a leaf if it has no children. The weighted tree is such a tree that each edge of this tree has some weight.
The weight of the path is the sum of edges weights on this path. The weight of the path from the vertex to itself is 00.
You can make a sequence of zero or more moves. On each move, you select an edge and divide its weight by 22 rounding down. More formally, during one move, you choose some edge ii and divide its weight by 22 rounding down (wi:=⌊wi2⌋wi:=⌊wi2⌋).
Your task is to find the minimum number of moves required to make the sum of weights of paths from the root to each leaf at most SS. In other words, if w(i,j)w(i,j) is the weight of the path from the vertex ii to the vertex jj, then you have to make ∑v∈leavesw(root,v)≤S∑v∈leavesw(root,v)≤S, where leavesleaves is the list of all leaves.
You have to answer tt independent test cases.
Input
The first line of the input contains one integer tt (1≤t≤2⋅1041≤t≤2⋅104) — the number of test cases. Then tt test cases follow.
The first line of the test case contains two integers nn and SS (2≤n≤105;1≤S≤10162≤n≤105;1≤S≤1016) — the number of vertices in the tree and the maximum possible sum of weights you have to obtain. The next n−1n−1 lines describe edges of the tree. The edge ii is described as three integers vivi, uiui and wiwi (1≤vi,ui≤n;1≤wi≤1061≤vi,ui≤n;1≤wi≤106), where vivi and uiui are vertices the edge ii connects and wiwi is the weight of this edge.
It is guaranteed that the sum of nn does not exceed 105105 (∑n≤105∑n≤105).
Output
For each test case, print the answer: the minimum number of moves required to make the sum of weights of paths from the root to each leaf at most SS.
Example
input
Copy
3
3 20
2 1 8
3 1 7
5 50
1 3 100
1 5 10
2 3 123
5 4 55
2 100
1 2 409
output
Copy
0
8
3
题意:一棵树,可以将任何边的权值减半,求需要操作多少次,使根节点到所有叶子节点的距离和sum小于等于s.
思路:首先dfs求出每个边被使用的次数,再求出该边权值减半后的缩小量,很明显,我们要先对缩小量大的树枝进行减半,可以利用set的自动排序,不停的减去最大缩小量,直到sum<=s.
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const int N = 2e5 + 10;
int n;
ll s;
typedef pair PII;
vector v[N];
ll cnt[N];
ll w[N];
void dfs(int u, int fa)
{
if(v[u].size() == 1)
{
cnt[fa] = 1;
}
for(auto a : v[u])
{
int v = a.first;
int e = a.second;
if(e == fa) continue;
dfs(v, e);
if(fa != -1) cnt[fa] += cnt[e];
}
}
ll get_sum(int i)
{
return cnt[i] * w[i] - w[i] / 2 * cnt[i];
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>s;
for(int i=1; i<=n; i++) v[i].clear();
memset(cnt, 0, sizeof cnt);
int a,b,c;
for(int i=0; i se;//自动从小到大排序
for(int i=0; i second;//rbegin()指向set最后一个元素,rend指向 set第一个元素前面的位置
ll a = se.rbegin() -> first;
sum -= a;
set :: iterator last = se.end();//end()指向最后一个元素的后一个元素
se.erase(--last);
w[id] /= 2;
se.insert({get_sum(id), id});
step++;
}
cout<