Pagini recente » Cod sursa (job #1280672) | Cod sursa (job #402516) | Cod sursa (job #1184264) | Cod sursa (job #1137965) | Cod sursa (job #1556225)
#include <fstream>
#include <bitset>
#include <cmath>
#include <random>
#include <iostream>
#include <cassert>
using namespace std;
const int MAX_N = 100000;
const int MAX_SQRT = 450;
const int MAX_V = 1e6;
const int NUM_SEARCH = 64;
const int NIL = -1;
struct Edge
{
int v;
int next;
};
Edge l[2 * MAX_N - 2];
int adj[MAX_N];
int E[MAX_N][2];
int nodeEuler[2 * MAX_N];
int eulerPtr;
bitset <MAX_V + 1> D[MAX_SQRT];
int lazy[MAX_SQRT];
int sum[MAX_N];
int BUCKET_SIZE;
int numBuckets;
void addEdge(int u, int v, int pos)
{
l[pos].v = v;
l[pos].next = adj[u];
adj[u] = pos;
}
void DFS(int u, int par)
{
E[u][0] = eulerPtr;
nodeEuler[eulerPtr] = u;
eulerPtr++;
for (int i = adj[u]; i != NIL; i = l[i].next)
if (l[i].v != par)
DFS(l[i].v, u);
E[u][1] = eulerPtr;
nodeEuler[eulerPtr] = NIL;
eulerPtr++;
}
inline int getRandom(void)
{
static mt19937 gen(time(0));
int x = gen();
if (x < 0)
x = -x;
return x;
}
int randomSearch(int sum)
{
for (int i = 0; i < NUM_SEARCH; i++)
{
int bucket = getRandom() % numBuckets;
if (sum >= lazy[bucket] && D[bucket][sum - lazy[bucket]])
return bucket;
}
return numBuckets;
}
int main()
{
ifstream in("arbore.in");
ofstream out("arbore.out");
in.tie(0);
ios_base::sync_with_stdio(0);
int N, M;
in >> N >> M;
for (int i = 0; i < N; i++)
adj[i] = NIL;
for (int i = 1; i < N; i++)
{
int u, v;
in >> u >> v;
addEdge(u - 1, v - 1, 2 * i - 2);
addEdge(v - 1, u - 1, 2 * i - 1);
}
DFS(0, -1);
BUCKET_SIZE = static_cast <int> (sqrt(eulerPtr - 1)) + 1;
numBuckets = (eulerPtr - 1) / BUCKET_SIZE + 1;
for (int i = 0; i < BUCKET_SIZE; i++)
D[i][0] = 1;
while (M--)
{
int opType;
in >> opType;
if (opType == 1)
{
int node, key, bucket, nextBucket;
in >> node >> key;
node--;
bucket = E[node][0] / BUCKET_SIZE;
nextBucket = (bucket + 1) * BUCKET_SIZE;
for (int i = bucket * BUCKET_SIZE; i < nextBucket; i++)
if (nodeEuler[i] != NIL)
D[bucket][ sum[ nodeEuler[i] ] ] = 0;
for (int i = E[node][0]; i < nextBucket && i < E[node][1]; i++)
if (nodeEuler[i] != NIL)
sum[ nodeEuler[i] ] += key;
for (int i = bucket * BUCKET_SIZE; i < nextBucket; i++)
if (nodeEuler[i] != NIL)
D[bucket][ sum[ nodeEuler[i] ] ] = 1;
if (E[node][0] / BUCKET_SIZE != E[node][1] / BUCKET_SIZE)
{
int ptr = (bucket + 1) * BUCKET_SIZE;
while (ptr + BUCKET_SIZE <= E[node][1])
{
lazy[ptr / BUCKET_SIZE] += key;
ptr += BUCKET_SIZE;
}
bucket = E[node][1] / BUCKET_SIZE;
nextBucket = (bucket + 1) * BUCKET_SIZE;
for (int i = bucket * BUCKET_SIZE; i < nextBucket; i++)
if (nodeEuler[i] != NIL)
D[bucket][ sum[ nodeEuler[i] ] ] = 0;
for (int i = bucket * BUCKET_SIZE; i < E[node][1]; i++)
if (nodeEuler[i] != NIL)
sum[ nodeEuler[i] ] += key;
for (int i = bucket * BUCKET_SIZE; i < nextBucket; i++)
if (nodeEuler[i] != NIL)
D[bucket][ sum[ nodeEuler[i] ] ] = 1;
}
}
else
{
int bucket, key;
in >> key;
bucket = 0;
while (bucket < numBuckets && (key < lazy[bucket] || !D[bucket][key - lazy[bucket]]))
bucket++;
if (bucket != numBuckets)
{
int eulerPos = bucket * BUCKET_SIZE;
int nextBucket = (bucket + 1) * BUCKET_SIZE;
key -= lazy[bucket];
while (eulerPos < nextBucket && (nodeEuler[eulerPos] == NIL || sum[ nodeEuler[eulerPos] ] != key))
eulerPos++;
assert(sum[nodeEuler[eulerPos]] == key);
out << nodeEuler[eulerPos] + 1 << '\n';
}
else
out << "-1\n";
}
}
in.close();
out.close();
return 0;
}