I encountered some runtime errors when I was trying to finish a A* algorithm for tsp problem. The program doesn't want to reach the main function. Here is my code, it is long.
#include <cmath>
#include <iostream>
#include <memory>
#include <queue>
#include <stdexcept>
#include <string>
#include <vector>
using namespace std;
constexpr const size_t R = 200; // Max Vertex number
pair<double, double> coordinate[ R ]{{1, 1}, {2, 2}, {1, 2}, {0, 0}};
// Index Min Priority Queue for double
class IndexMinPQ {
private:
const size_t maxN;
size_t n;
size_t *pq, *qp;
double* elem;
void exch(size_t i, size_t j) {
swap(pq[ i ], pq[ j ]);
swap(qp[ pq[ i ] ], qp[ pq[ j ] ]);
}
void swim(size_t k) {
while (k > 1 && elem[ pq[ k / 2 ] ] > elem[ pq[ k ] ]) {
exch(k, k / 2);
k = k / 2;
}
}
void sink(size_t k) {
while (2 * k <= n) {
int j = 2 * k;
if (j < n && elem[ pq[ j ] ] > elem[ pq[ j + 1 ] ]) ++j;
if (elem[ pq[ k ] ] <= elem[ pq[ j ] ]) break;
exch(k, j);
k = j;
}
}
inline void validateIndex(size_t i) const {
if (i >= maxN) throw invalid_argument("index >= capacity: " + to_string(i));
}
public:
IndexMinPQ(size_t maxN)
: maxN(maxN), n(0), pq(new size_t[ maxN + 1 ]), qp(new size_t[ maxN + 1 ]),
elem(new double[ maxN + 1 ]) {
for (size_t i = 0; i <= maxN; ++i)
qp[ i ] = 0;
}
IndexMinPQ(const IndexMinPQ& orig)
: maxN(orig.maxN), n(orig.n), pq(new size_t[ maxN + 1 ]),
qp(new size_t[ maxN + 1 ]), elem(new double[ maxN + 1 ]) {
copy(orig.pq, orig.pq + n + 1, pq);
copy(orig.qp, orig.qp + n + 1, qp);
copy(orig.elem, orig.elem + n + 1, elem);
}
IndexMinPQ& operator=(const IndexMinPQ&) = delete;
~IndexMinPQ() {
delete[] pq;
delete[] qp;
delete[] elem;
}
void insert(size_t i, double val) {
validateIndex(i);
if (n == maxN) throw overflow_error("priority queue is full");
if (contains(i)) throw invalid_argument("index is already in the priority queue");
++n;
qp[ i ] = n;
elem[ i ] = val;
pq[ n ] = i;
swim(n);
}
bool contains(int i) const {
validateIndex(i);
return qp[ i ] != 0;
}
void delElem(size_t i) {
validateIndex(i);
if (!contains(i)) {
// throw invalid_argument("index is not in the priority queue");
return;
}
int index = qp[ i ];
exch(index, n--);
swim(index);
sink(index);
elem[ i ] = 0.0;
qp[ i ] = 0;
}
size_t size() const { return n; }
double minElem() const {
if (n == 0) throw underflow_error("priority queue is empty");
return elem[ pq[ 1 ] ];
}
};
// Weighted Edge
class Edge {
private:
const size_t no;
const size_t v;
const size_t w;
const double wei;
public:
Edge(size_t No, size_t v, size_t w, double weight)
: no(No), v(v), w(w), wei(weight) {}
double weight() const { return this->wei; }
size_t No() const { return no; }
size_t either() const { return v; }
size_t other(int vertex) const {
if (vertex == v)
return w;
else if (vertex == w)
return v;
else
throw invalid_argument("Inconsistent edge");
}
};
class Graph {
private:
const size_t V; // number of Vertexs
const size_t E; // number of Edges=V*(V-1)/2
Edge* edges; // All Edges
vector<size_t>* Adj; // adjcent table
public:
Graph(size_t V) : V(V), E(V * (V - 1) / 2), Adj(new vector<size_t>[ V ]) {
allocator<Edge> alloc; // detach memory allocating and item constructing
edges = alloc.allocate(E);
size_t cnt = 0;
for (size_t i = 0; i < V - 1; ++i)
for (size_t j = i + 1; j < V; ++j) {
double dx = coordinate[ i ].first - coordinate[ j ].first,
dy = coordinate[ i ].second - coordinate[ j ].second;
// Euclid distance between two Vertexs
alloc.construct(edges + cnt, cnt, i, j, sqrt(dx * dx + dy * dy));
cnt++;
}
// construct adjcent table
for (size_t i = 0; i < E; ++i) {
size_t v = edges[ i ].either(), w = edges[ i ].other(v);
Adj[ v ].push_back(i);
Adj[ w ].push_back(i);
}
}
~Graph() {
delete[] Adj;
allocator<Edge> alloc;
for (size_t i = 0; i < E; ++i)
alloc.destroy(edges + i);
alloc.deallocate(edges, E);
}
inline size_t sizeV() const { return V; }
inline size_t sizeE() const { return E; }
inline const Edge& getEdge(size_t e) const {
if (e >= E)
throw invalid_argument("index >= edges: V * (V - 1) / 2 =" + to_string(E));
return edges[ e ];
}
inline const vector<size_t>& adj(size_t v) const {
if (v >= V) throw invalid_argument("index >= vetexs: " + to_string(V));
return Adj[ v ];
}
};
struct Aux {
const Graph& G;
vector<size_t> path;
bool* marked;
IndexMinPQ pq;
double dist;
double evaluate;
Aux(const Graph& G)
: G(G), marked(new bool[ G.sizeV() ]), pq(G.sizeE()), dist(0), evaluate(0) {
for (size_t i = 1; i < G.sizeV(); ++i)
marked[ i ] = false;
marked[ 0 ] = true;
path.push_back(0);
for (size_t i = G.sizeV() - 1; i < G.sizeE(); ++i)
pq.insert(i, G.getEdge(i).weight());
}
~Aux() { delete[] marked; }
Aux(const Aux&) = delete;
Aux& operator=(const Aux&) = delete;
Aux(const Aux& orgi, const Edge& e)
: G(orgi.G), marked(new bool[ G.sizeV() ]), pq(orgi.pq), dist(orgi.dist) {
copy(orgi.marked, orgi.marked + G.sizeV(), marked);
size_t v = path.back(), w = e.other(v);
if (marked[ w ]) throw invalid_argument("already in path");
dist += e.weight();
evaluate = dist + (G.sizeV() - path.size() + 1) * pq.minElem();
for (const size_t& e : G.adj(w))
pq.delElem(e);
}
};
vector<size_t> AStar(const Graph& G) {
auto cmp = [](Aux* lhs, Aux* rhs) -> bool { return lhs->evaluate > rhs->evaluate; };
priority_queue<Aux*, vector<Aux*>, decltype(cmp)> pq(cmp);
Aux* t = new Aux(G);
pq.push(t);
while (true) {
Aux* a = pq.top();
pq.pop();
if (a->path.size() == G.sizeV()) return a->path;
size_t v = a->path.back();
for (size_t ind : G.adj(v)) {
const Edge& e = G.getEdge(ind);
size_t w = e.other(v);
if (!a->marked[ w ]) {
Aux* t2 = new Aux(*a, e);
pq.push(t2);
}
}
delete a;
}
// throw runtime_error("impossible to reach");
return vector<size_t>();
}
int main() {
// AStar(Graph(4));
system("pause");
return 0;
}
The compilier didn't say anything. However,
it won't goto the main function and flashed over the screen. I tried to set breakpoint, but it didn't hit, what the gdb says was:
(gdb) r
Starting program: D:\cs\c++\exercise\source3.exe
[New Thread 8152.0x1aec]
[New Thread 8152.0x3254]
[New Thread 8152.0x1740]
[New Thread 8152.0x288]
Mingw-w64 runtime failure:
Unknown pseudo relocation protocol version 256.
[Thread 8152.0x3254 exited with code 3]
[Thread 8152.0x1740 exited with code 3]
[Thread 8152.0x288 exited with code 3]
[Inferior 1 (process 8152) exited with code 03]
However, after I commented the function AStar(line 191-213), the problem disappeared. What is the problem?
You call back() on an empty vector. But please use a (good) debugger before posting here! GDB is good but no really easy to use...
size_t v = a->path.back();
Related
This question already has answers here:
How can I sort two vectors in the same way, with criteria that uses only one of the vectors?
(9 answers)
Closed 9 months ago.
I have this code here that has two arrays. It sorts arr[], so that the highest value will be in index 0. Now the second array arr1[] contains strings, I'd like the code to apply whatever changes where made to arr[] to arr1[]. So that arr[0] would return 6, while arr1[0] would return the string "d1". Notice how "d1" was at the same index as 6? After sorting I'd like the same values to still have their string counterparts.
How would I go about doing this?
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <functional>
using namespace std;
int main() {
int arr[ 5 ] = { 4, 1, 3, 6, 2 };
string arr1[ 5 ] = { "a1", "b1", "c1", "d1", "e1" };
std::sort( arr, arr + 5, std::greater< int >() );
cout << arr[0] << arr1[0] << endl;
system("pause");
}
Rather than sort the arrays, sort the indices. I.e., you have
int arr[5]={4,1,3,6,2}
string arr1[5]={"a1","b1","c1","d1","e1"};
and you make
int indices[5]={0,1,2,3,4};
now you make a sort indices comparator that looks like this (just and idea, you'll probably have to fix it a little)
class sort_indices
{
private:
int* mparr;
public:
sort_indices(int* parr) : mparr(parr) {}
bool operator()(int i, int j) const { return mparr[i]<mparr[j]; }
}
now you can use the stl sort
std::sort(indices, indices+5, sort_indices(arr));
when you're done, the indices array will be such that arr[indices[0]] is the first element. and likewise arr1[indices[0]] is the corresponding pair.
This is also a very useful trick when you're trying to sort a large data object, you don't need to move the data around at every swap, just the indices.
You need to combine them together and then sort the combined pair and then un-combine the pairs.
int arr[ 5 ] = { ... };
string arr1[ 5 ] = { ... };
pair<int, string> pairs[ 5 ];
for ( int i = 0; i < 5; ++i )
pairs[ i ] = make_pair( arr[ i ], arr1[ i ] );
sort( pairs.begin(), pairs.end() );
for ( int i = 0; i < 5; ++i )
{
arr[ i ] = pairs[ i ].first;
arr1[ i ] = pairs[ i ].second;
}
Really though, if arr and arr1 are related then they should be stored as the pair (or at least a custom struct) anyway. That way you don't need to use this as an intermediate step.
Write your own iterator and use STD:sort. It's easily coded in less than 50 lines without 3rd party libraries.
Swap function IS VERY IMPORTANT here.
#include <iostream>
#include <iterator> // std::iterator, std::input_iterator_tag
#include <algorithm>
using namespace std;
struct Tuple;
struct RefTuple;
#define TUPLE_COMMON_FUNC(C, D, E, F) \
C##::C## (Tuple& t) ##D \
C##::C## (RefTuple& t) ##D \
void C##::operator = (Tuple& t) ##E \
void C##::operator = (RefTuple& t) ##E \
bool C##::operator < (const Tuple& t) const ##F \
bool C##::operator < (const RefTuple& t) const ##F
#define ASSIGN_1 : i(t.i), j(t.j), s(t.s) {}
#define ASSIGN_2 { i = t.i; j = t.j; s = t.s; }
#define SORT_CRITERIA \
return (j < t.j) || (j == t.j && (i < t.i));
struct Tuple {
int i, j, s;
TUPLE_COMMON_FUNC(Tuple, ; , ; , ;)
};
struct RefTuple {
int &i, &j, &s;
RefTuple(int &x, int &y, int &z): i(x), j(y), s(z) {}
TUPLE_COMMON_FUNC(RefTuple, ; , ; , ;)
};
TUPLE_COMMON_FUNC(Tuple, ASSIGN_1, ASSIGN_2, {SORT_CRITERIA})
TUPLE_COMMON_FUNC(RefTuple, ASSIGN_1, ASSIGN_2, {SORT_CRITERIA})
void swap(RefTuple& t1, RefTuple& t2) {
t1.i ^= t2.i; t2.i ^= t1.i; t1.i ^= t2.i;
t1.j ^= t2.j; t2.j ^= t1.j; t1.j ^= t2.j;
t1.s ^= t2.s; t2.s ^= t1.s; t1.s ^= t2.s;
}
class IterTuple : public iterator<random_access_iterator_tag, Tuple> {
int *i, *j, *s, idx;
public:
IterTuple(int* x, int*y, int* z, int l) : i(x), j(y), s(z), idx(l) {}
IterTuple(const IterTuple& e) : i(e.i), j(e.j), s(e.s), idx(e.idx) {}
RefTuple operator*() { return RefTuple(i[idx], j[idx], s[idx]); }
IterTuple& operator ++ () { idx++; return *this; }
IterTuple& operator -- () { idx--; return *this; }
IterTuple operator ++ (int) { IterTuple tmp(*this); idx++; return tmp; }
IterTuple operator -- (int) { IterTuple tmp(*this); idx--; return tmp; }
int operator - (IterTuple& rhs) { return idx - rhs.idx; }
IterTuple operator + (int n) { IterTuple tmp(*this); tmp.idx += n; return tmp; }
IterTuple operator - (int n) { IterTuple tmp(*this); tmp.idx -= n; return tmp; }
bool operator==(const IterTuple& rhs) { return idx == rhs.idx; }
bool operator!=(const IterTuple& rhs) { return idx != rhs.idx; }
bool operator<(IterTuple& rhs) { return idx < rhs.idx; }
};
int Ai[10] = {0, 0, 2, 3, 2, 4, 1, 1, 4, 2};
int Aj[10] = {0, 2, 3, 4, 4, 4, 0, 1, 0, 2};
int Ax[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int main () {
IterTuple from(Ai, Aj, Ax, 0);
IterTuple until(Ai, Aj, Ax, 10);
sort(from, until);
for (IterTuple it = from; it != until; it++)
cout << (*it).i << ' ' << (*it).j << ' ' << (*it).s << '\n';
return 0;
}
I believe that writting your own QuickSort variant is simplier and the result will perform better then mapping custom iterators or array with indices.
QuickSort is not stable sort.
template<class A, class B> void QuickSort2Desc(A a[], B b[], int l, int r)
{
int i = l;
int j = r;
A v = a[(l + r) / 2];
do {
while (a[i] > v)i++;
while (v > a[j])j--;
if (i <= j)
{
std::swap(a[i], a[j]);
std::swap(b[i], b[j]);
i++;
j--;
};
} while (i <= j);
if (l < j)QuickSort2Desc(a, b, l, j);
if (i < r)QuickSort2Desc(a, b, i, r);
}
I was learning MO's Algorithm. In that I found a question. In which we have to make a program to take input n for n nodes of a tree then n-1 pairs of u and v denoting the connection between node u and node v. After that giving the n node values.
Then we will ask q queries. For each query we take input of k and l which denote the two nodes of that tree. Now we have to find the product of all the nodes in the path of k and l (including k and l).
I want to use MO's algorithm. https://codeforces.com/blog/entry/43230
But I am unable to make the code. Can anybody help me out in this.
The basic code for that would be:
int n, q;
int nxt[ N ], to[ N ], hd[ N ];
struct Que{
int u, v, id;
} que[ N ];
void init() {
// read how many nodes and how many queries
cin >> n >> q;
// read the edge of tree
for ( int i = 1 ; i < n ; ++ i ) {
int u, v; cin >> u >> v;
// save the tree using adjacency list
nxt[ i << 1 | 0 ] = hd[ u ];
to[ i << 1 | 0 ] = v;
hd[ u ] = i << 1 | 0;
nxt[ i << 1 | 1 ] = hd[ v ];
to[ i << 1 | 1 ] = u;
hd[ v ] = i << 1 | 1;
}
for ( int i = 0 ; i < q ; ++ i ) {
// read queries
cin >> que[ i ].u >> que[ i ].v;
que[ i ].id = i;
}
}
int dfn[ N ], dfn_, block_id[ N ], block_;
int stk[ N ], stk_;
void dfs( int u, int f ) {
dfn[ u ] = dfn_++;
int saved_rbp = stk_;
for ( int v_ = hd[ u ] ; v_ ; v_ = nxt[ v_ ] ) {
if ( to[ v_ ] == f ) continue;
dfs( to[ v_ ], u );
if ( stk_ - saved_rbp < SQRT_N ) continue;
for ( ++ block_ ; stk_ != saved_rbp ; )
block_id[ stk[ -- stk_ ] ] = block_;
}
stk[ stk_ ++ ] = u;
}
bool inPath[ N ];
void SymmetricDifference( int u ) {
if ( inPath[ u ] ) {
// remove this edge
} else {
// add this edge
}
inPath[ u ] ^= 1;
}
void traverse( int& origin_u, int u ) {
for ( int g = lca( origin_u, u ) ; origin_u != g ; origin_u = parent_of[ origin_u ] )
SymmetricDifference( origin_u );
for ( int v = u ; v != origin_u ; v = parent_of[ v ] )
SymmetricDifference( v );
origin_u = u;
}
void solve() {
// construct blocks using dfs
dfs( 1, 1 );
while ( stk_ ) block_id[ stk[ -- stk_ ] ] = block_;
// re-order our queries
sort( que, que + q, [] ( const Que& x, const Que& y ) {
return tie( block_id[ x.u ], dfn[ x.v ] ) < tie( block_id[ y.u ], dfn[ y.v ] );
} );
// apply mo's algorithm on tree
int U = 1, V = 1;
for ( int i = 0 ; i < q ; ++ i ) {
pass( U, que[ i ].u );
pass( V, que[ i ].v );
// we could our answer of que[ i ].id
}
}
This problem is a slight modification of the blog that you have shared.
Problem Tags:- MO's Algorithm, Trees, LCA, Binary Lifting, Sieve, Precomputation, Prime Factors
Precomputations:- Just we need to do some precomputations with seiveOfErothenesis to store the highest prime factor of each element possible in input constraints. Then using this we will store all the prime factors and their powers for each element in input array in another matrix.
Observation:- with the constraints you can see the there can be very few such primes possible for each element. For an element (10^6) there can be a maximum of 7 prime factors possible.
Modify MO Algo Given in blog:- Now in our compute method we just need to maintain a map that will store the current count of the prime factor. While adding or subtracting each element in solving the queries we will iterate on the prime factors of that element and divide our result(storing total no. of factors) with the old count of that prime and then update the count of that prime and the multiple our result with the new count.(This will be O(7) max for each addition/subtraction).
Complexity:- O(T * ((N + Q) * sqrt(N) * F)) where F is 7 in our case. F is the complexity of your check method().
T - no of test cases in input file.
N - the size of your input array.
Q - No. of queries.
Below is an implementation of the above approach in JAVA. computePrimePowers() and check() are the methods you would be interested in.
import java.util.*;
import java.io.*;
public class Main {
static int BLOCK_SIZE;
static int ar[];
static ArrayList<Integer> graph[];
static StringBuffer sb = new StringBuffer();
static boolean notPrime[] = new boolean[1000001];
static int hpf[] = new int[1000001];
static void seive(){
notPrime[0] = true;
notPrime[1] = true;
for(int i = 2; i < 1000001; i++){
if(!notPrime[i]){
hpf[i] = i;
for(int j = 2 * i; j < 1000001; j += i){
notPrime[j] = true;
hpf[j] = i;
}
}
}
}
static long modI[] = new long[1000001];
static void computeModI() {
for(int i = 1; i < 1000001; i++) {
modI[i] = pow(i, 1000000005);
}
}
static long pow(long x, long y) {
if (y == 0)
return 1;
long p = pow(x, y / 2);
p = (p >= 1000000007) ? p % 1000000007 : p;
p = p * p;
p = (p >= 1000000007) ? p % 1000000007 : p;
if ((y & 1) == 0)
return p;
else {
long tt = x * p;
return (tt >= 1000000007) ? tt % 1000000007 : tt;
}
}
public static void main(String[] args) throws Exception {
Reader s = new Reader();
int test = s.nextInt();
seive();
computeModI();
for(int ii = 0; ii < test; ii++){
int n = s.nextInt();
lcaTable = new int[19][n + 1];
graph = new ArrayList[n + 1];
arrPrimes = new int[n + 1][7][2];
primeCnt = new int[1000001];
visited = new int[n + 1];
ar = new int[n + 1];
for(int i = 0; i < graph.length; i++) graph[i] = new ArrayList<>();
for(int i = 1; i < n; i++){
int u = s.nextInt(), v = s.nextInt();
graph[u].add(v);
graph[v].add(u);
}
int ip = 1; while(ip <= n) ar[ip++] = s.nextInt();
computePrimePowers();
int q = s.nextInt();
LVL = new int[n + 1];
dfsTime = 0;
dfs(1, -1);
BLOCK_SIZE = (int) Math.sqrt(dfsTime);
int Q[][] = new int[q][4];
int i = 0;
while(q-- > 0) {
int u = s.nextInt(), v = s.nextInt();
Q[i][0] = lca(u, v);
if (l[u] > l[v]) {
int temp = u; u = v; v = temp;
}
if (Q[i][0] == u) {
Q[i][1] = l[u];
Q[i][2] = l[v];
}
else {
Q[i][1] = r[u]; // left at col1 in query
Q[i][2] = l[v]; // right at col2
}
Q[i][3] = i;
i++;
}
Arrays.sort(Q, new Comparator<int[]>() {
#Override
public int compare(int[] x, int[] y) {
int block_x = (x[1] - 1) / (BLOCK_SIZE + 1);
int block_y = (y[1] - 1) / (BLOCK_SIZE + 1);
if(block_x != block_y)
return block_x - block_y;
return x[2] - y[2];
}
});
solveQueries(Q);
}
System.out.println(sb);
}
static long res;
private static void solveQueries(int [][] Q) {
int M = Q.length;
long results[] = new long[M];
res = 1;
int curL = Q[0][1], curR = Q[0][1] - 1;
int i = 0;
while(i < M){
while (curL < Q[i][1]) check(ID[curL++]);
while (curL > Q[i][1]) check(ID[--curL]);
while (curR < Q[i][2]) check(ID[++curR]);
while (curR > Q[i][2]) check(ID[curR--]);
int u = ID[curL], v = ID[curR];
if (Q[i][0] != u && Q[i][0] != v) check(Q[i][0]);
results[Q[i][3]] = res;
if (Q[i][0] != u && Q[i][0] != v) check(Q[i][0]);
i++;
}
i = 0;
while(i < M) sb.append(results[i++] + "\n");
}
static int visited[];
static int primeCnt[];
private static void check(int x) {
if(visited[x] == 1){
for(int i = 0; i < 7; i++) {
int c = arrPrimes[x][i][1];
int pp = arrPrimes[x][i][0];
if(pp == 0) break;
long tem = res * modI[primeCnt[pp] + 1];
res = (tem >= 1000000007) ? tem % 1000000007 : tem;
primeCnt[pp] -= c;
tem = res * (primeCnt[pp] + 1);
res = (tem >= 1000000007) ? tem % 1000000007 : tem;
}
}
else if(visited[x] == 0){
for(int i = 0; i < 7; i++) {
int c = arrPrimes[x][i][1];
int pp = arrPrimes[x][i][0];
if(pp == 0) break;
long tem = res * modI[primeCnt[pp] + 1];
res = (tem >= 1000000007) ? tem % 1000000007 : tem;
primeCnt[pp] += c;
tem = res * (primeCnt[pp] + 1);
res = (tem >= 1000000007) ? tem % 1000000007 : tem;
}
}
visited[x] ^= 1;
}
static int arrPrimes[][][];
static void computePrimePowers() {
int n = arrPrimes.length;
int i = 0;
while(i < n) {
int ele = ar[i];
int k = 0;
while(ele > 1) {
int c = 0;
int pp = hpf[ele];
while(hpf[ele] == pp) {
c++; ele /= pp;
}
arrPrimes[i][k][0] = pp;
arrPrimes[i][k][1] = c;
k++;
}
i++;
}
}
static int dfsTime;
static int l[] = new int[1000001], r[] = new int[1000001], ID[] = new int[1000001], LVL[], lcaTable[][];
static void dfs(int u, int p){
l[u] = ++dfsTime;
ID[dfsTime] = u;
int i = 1;
while(i < 19) {
lcaTable[i][u] = lcaTable[i - 1][lcaTable[i - 1][u]];
i++;
}
i = 0;
while(i < graph[u].size()){
int v = graph[u].get(i);
i++;
if (v == p) continue;
LVL[v] = LVL[u] + 1;
lcaTable[0][v] = u;
dfs(v, u);
}
r[u] = ++dfsTime;
ID[dfsTime] = u;
}
static int lca(int u, int v){
if (LVL[u] > LVL[v]) {
int temp = u;
u = v; v = temp;
}
int i = 18;
while(i >= 0) {
if (LVL[v] - (1 << i) >= LVL[u]) v = lcaTable[i][v];
i--;
}
if (u == v) return u;
i = 18;
while(i >= 0){
if (lcaTable[i][u] != lcaTable[i][v]){
u = lcaTable[i][u];
v = lcaTable[i][v];
}
i--;
}
return lcaTable[0][u];
}
}
// SIMILAR SOLUTION FOR FINDING NUMBER OF DISTINCT ELEMENTS FROM U TO V
// USING MO's ALGORITHM
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 40005;
const int MAXM = 100005;
const int LN = 19;
int N, M, K, cur, A[MAXN], LVL[MAXN], DP[LN][MAXN];
int BL[MAXN << 1], ID[MAXN << 1], VAL[MAXN], ANS[MAXM];
int d[MAXN], l[MAXN], r[MAXN];
bool VIS[MAXN];
vector < int > adjList[MAXN];
struct query{
int id, l, r, lc;
bool operator < (const query& rhs){
return (BL[l] == BL[rhs.l]) ? (r < rhs.r) : (BL[l] < BL[rhs.l]);
}
}Q[MAXM];
// Set up Stuff
void dfs(int u, int par){
l[u] = ++cur;
ID[cur] = u;
for (int i = 1; i < LN; i++) DP[i][u] = DP[i - 1][DP[i - 1][u]];
for (int i = 0; i < adjList[u].size(); i++){
int v = adjList[u][i];
if (v == par) continue;
LVL[v] = LVL[u] + 1;
DP[0][v] = u;
dfs(v, u);
}
r[u] = ++cur; ID[cur] = u;
}
// Function returns lca of (u) and (v)
inline int lca(int u, int v){
if (LVL[u] > LVL[v]) swap(u, v);
for (int i = LN - 1; i >= 0; i--)
if (LVL[v] - (1 << i) >= LVL[u]) v = DP[i][v];
if (u == v) return u;
for (int i = LN - 1; i >= 0; i--){
if (DP[i][u] != DP[i][v]){
u = DP[i][u];
v = DP[i][v];
}
}
return DP[0][u];
}
inline void check(int x, int& res){
// If (x) occurs twice, then don't consider it's value
if ( (VIS[x]) and (--VAL[A[x]] == 0) ) res--;
else if ( (!VIS[x]) and (VAL[A[x]]++ == 0) ) res++;
VIS[x] ^= 1;
}
void compute(){
// Perform standard Mo's Algorithm
int curL = Q[0].l, curR = Q[0].l - 1, res = 0;
for (int i = 0; i < M; i++){
while (curL < Q[i].l) check(ID[curL++], res);
while (curL > Q[i].l) check(ID[--curL], res);
while (curR < Q[i].r) check(ID[++curR], res);
while (curR > Q[i].r) check(ID[curR--], res);
int u = ID[curL], v = ID[curR];
// Case 2
if (Q[i].lc != u and Q[i].lc != v) check(Q[i].lc, res);
ANS[Q[i].id] = res;
if (Q[i].lc != u and Q[i].lc != v) check(Q[i].lc, res);
}
for (int i = 0; i < M; i++) printf("%d\n", ANS[i]);
}
int main(){
int u, v, x;
while (scanf("%d %d", &N, &M) != EOF){
// Cleanup
cur = 0;
memset(VIS, 0, sizeof(VIS));
memset(VAL, 0, sizeof(VAL));
for (int i = 1; i <= N; i++) adjList[i].clear();
// Inputting Values
for (int i = 1; i <= N; i++) scanf("%d", &A[i]);
memcpy(d + 1, A + 1, sizeof(int) * N);
// Compressing Coordinates
sort(d + 1, d + N + 1);
K = unique(d + 1, d + N + 1) - d - 1;
for (int i = 1; i <= N; i++) A[i] = lower_bound(d + 1, d + K + 1, A[i]) - d;
// Inputting Tree
for (int i = 1; i < N; i++){
scanf("%d %d", &u, &v);
adjList[u].push_back(v);
adjList[v].push_back(u);
}
// Preprocess
DP[0][1] = 1;
dfs(1, -1);
int size = sqrt(cur);
for (int i = 1; i <= cur; i++) BL[i] = (i - 1) / size + 1;
for (int i = 0; i < M; i++){
scanf("%d %d", &u, &v);
Q[i].lc = lca(u, v);
if (l[u] > l[v]) swap(u, v);
if (Q[i].lc == u) Q[i].l = l[u], Q[i].r = l[v];
else Q[i].l = r[u], Q[i].r = l[v];
Q[i].id = i;
}
sort(Q, Q + M);
compute();
}
}
Demo
The problem is, in a table of (h+1)*(w+1),the first row contains w values: a[1] ... a[w] which fill in the 2rd ... (w+1)th column. The first column contains h values: b[1] ... b[h] which fill in the 2rd ... (h+1)th row. sum(a[i]) is equal to sum(b[i]).
The question is to give one possible solution: result, so that sum(result[i][K]) for a certain K, is equal to a[i] with result[i][K] != result[j][K] (i != j and 0 < i < h+1). And the same rule for rows. PS: All the integers are positive.
For example:
a[] = {10, 3, 3}, b[] = {9, 7}
// 10 3 3
// 9 6 2 1
// 7 4 1 2
result = {6, 2, 1;
4, 1, 2}
It is like Kakuro but not the same. I cannot figure out which algorithm to apply, if anyone knows how to solve it, please give me some help. Thanks a lot.
You can always solve your problem with backtracking. Basic idea here: from top-to-bottom and left-to-right try a valid value in the partially filled table, backtrack when this value doesn't lead to a solution.
Minimal example in C++ with annotated solve:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <memory>
class Problem {
public:
template<class AIter, class BIter>
Problem(AIter abegin, AIter aend, BIter bbegin, BIter bend)
: m_width(std::distance(abegin, aend))
, m_height(std::distance(bbegin, bend))
, m_table(new int[(m_width + 1) * (m_height + 1)])
{
std::fill(m_table.get(), m_table.get() + (m_width + 1) * (m_height + 1), 0);
for(size_t i = 0; i < m_width; ++i)
m_table[i + 1] = *abegin++;
for(size_t j = 0; j < m_height; ++j)
m_table[(j + 1) * (m_width + 1)] = *bbegin++;
}
bool Solve() { return solve(0, 0); }
int operator()(size_t i, size_t j) const;
private:
int a(size_t i) const { return m_table[i + 1]; }
int b(size_t j) const { return m_table[(j + 1) * (m_width + 1)]; }
int get(size_t i, size_t j) const { return m_table[(j + 1) * (m_width + 1) + i + 1]; }
void set(size_t i, size_t j, int value) { m_table[(j + 1) * (m_width + 1) + i + 1] = value; }
int colSum(size_t i) const;
int rowSum(size_t j) const;
bool solve(size_t i, size_t j);
size_t m_width, m_height;
std::unique_ptr<int[]> m_table; // (width + 1) x (height + 1)
};
int Problem::colSum(size_t i) const {
int sum = 0;
for(size_t j = 0; j < m_height; ++j)
sum += get(i, j);
return sum;
}
int Problem::rowSum(size_t j) const {
int sum = 0;
for(size_t i = 0; i < m_width; ++i)
sum += get(i, j);
return sum;
}
// solves column-wise using backtracking
bool Problem::solve(size_t i, size_t j) {
size_t width = m_width, height = m_height;
// past last column?
if(i >= width) {
// found solution
return true;
}
// remainder in column and row
int remColSum = a(i) - colSum(i);
int remRowSum = b(j) - rowSum(j);
// early break
if(remColSum <= 0 || remRowSum <= 0)
return false;
// starting at the minimal required value (1 or remColSum if on last row)
int startValue = j + 1 < height ? 1 : remColSum;
// remaining row sum cannot support the starting value
if(remRowSum < startValue)
return false;
// end value minimum remaining sum
int endValue = remColSum < remRowSum ? remColSum : remRowSum;
// on last element must equal starting value
if(i + 1 == width && j + 1 == height && startValue != endValue)
return false;
// column-wise i.e. next cell is (i, j + 1) wrapped
int nextI = i + (j + 1) / height;
int nextJ = (j + 1) % height;
for(int value = startValue; value <= endValue; ++value) {
bool valid = true;
// check row up to i
for(size_t u = 0; u < i && valid; ++u)
valid = (get(u, j) != value);
// check column up to j
for(size_t v = 0; v < j && valid; ++v)
valid = (get(i, v) != value);
if(!valid) {
// value is invalid in partially filled table
continue;
}
// value produces a valid, partially filled table, now try recursing
set(i, j, value);
// upon first solution break
if(solve(nextI, nextJ))
return true;
}
// upon failure backtrack
set(i, j, 0);
return false;
}
int Problem::operator()(size_t i, size_t j) const {
return get(i, j);
}
int main() {
int a[] = { 10, 3, 3 };
int b[] = { 9, 7 };
size_t width = sizeof(a) / sizeof(*a);
size_t height = sizeof(b) / sizeof(*b);
Problem problem(a, a + width, b, b + height);
if(!problem.Solve()) {
std::cout << "No solution" << std::endl;
}
for(size_t j = 0; j < height; ++j) {
if(j == 0) {
std::cout << " ";
for(size_t i = 0; i < width; ++i)
std::cout << " " << a[i];
std::cout << std::endl;
}
std::cout << b[j];
for(size_t i = 0; i < width; ++i) {
int value = problem(i, j);
if(value == 0)
std::cout << " ";
else
std::cout << " " << value;
}
std::cout << std::endl;
}
return 0;
}
Searching for the best algorithm I found there is a tradeoff: complexity to implement and big constant on the one hand, and runtime complexity on the other hand. I choose LU-decomposition-based algorithm, because it is quite simple to implement and have good enough performance.
#include <valarray>
#include <vector>
#include <utility>
#include <cmath>
#include <cstddef>
#include <cassert>
template< typename value_type >
struct math
{
using size_type = std::size_t;
size_type const dimension_;
value_type const & eps;
value_type const zero = value_type(0);
value_type const one = value_type(1);
private :
using vector = std::valarray< value_type >;
using matrix = std::vector< vector >;
matrix matrix_;
matrix minor_;
public :
math(size_type const _dimension,
value_type const & _eps)
: dimension_(_dimension)
, eps(_eps)
, matrix_(dimension_)
, minor_(dimension_ - 1)
{
assert(1 < dimension_);
assert(!(eps < zero));
for (size_type r = 0; r < dimension_; ++r) {
matrix_[r].resize(dimension_);
}
size_type const minor_size = dimension_ - 1;
for (size_type r = 0; r < minor_size; ++r) {
minor_[r].resize(minor_size);
}
}
template< typename rhs = matrix >
void
operator = (rhs const & _matrix)
{
auto irow = std::begin(matrix_);
for (auto const & row_ : _matrix) {
auto icol = std::begin(*irow);
for (auto const & v : row_) {
*icol = v;
++icol;
}
++irow;
}
}
value_type
det(matrix & _matrix,
size_type const _dimension)
{ // calculates lower unit triangular matrix and upper triangular
assert(0 < _dimension);
value_type det_ = one;
for (size_type i = 0; i < _dimension; ++i) {
vector & ri_ = _matrix[i];
using std::abs;
value_type max_ = abs(ri_[i]);
size_type pivot = i;
{
size_type p = i;
while (++p < _dimension) {
value_type y_ = abs(_matrix[p][i]);
if (max_ < y_) {
max_ = std::move(y_);
pivot = p;
}
}
}
if (!(eps < max_)) { // regular?
return zero; // singular
}
if (pivot != i) {
det_ = -det_; // each permutation flips sign of det
ri_.swap(_matrix[pivot]);
}
value_type & dia_ = ri_[i];
det_ *= dia_; // det is multiple of diagonal elements
for (size_type j = 1 + i; j < _dimension; ++j) {
_matrix[j][i] /= dia_;
}
for (size_type a = 1 + i; a < _dimension; ++a) {
vector & a_ = minor_[a - 1];
value_type const & ai_ = _matrix[a][i];
for (size_type b = 1 + i; b < _dimension; ++b) {
a_[b - 1] = ai_ * ri_[b];
}
}
for (size_type a = 1 + i; a < _dimension; ++a) {
vector const & a_ = minor_[a - 1];
vector & ra_ = _matrix[a];
for (size_type b = 1 + i; b < _dimension; ++b) {
ra_[b] -= a_[b - 1];
}
}
}
return det_;
}
value_type
det(size_type const _dimension)
{
return det(matrix_, _dimension);
}
value_type
det()
{
return det(dimension_);
}
};
// main.cpp
#include <iostream>
#include <cstdlib>
int
main()
{
using value_type = double;
value_type const eps = std::numeric_limits< value_type >::epsilon();
std::size_t const dimension_ = 3;
math< value_type > m(dimension_, eps);
m = { // example from https://en.wikipedia.org/wiki/Determinant#Laplace.27s_formula_and_the_adjugate_matrix
{-2.0, 2.0, -3.0},
{-1.0, 1.0, 3.0},
{ 2.0, 0.0, -1.0}
};
std::cout << m.det() << std::endl; // 18
return EXIT_SUCCESS;
}
LIVE DEMO
det() function is hottest function in the algorithm, that uses it as a part. I sure det() is not as fast as it can be, because runtime performance comparisons (using google-pprof) to reference implementation of the whole algorithm shows a disproportion towards det().
How to improve performance of det() function? What are evident optimizations to apply immediately? Should I change the indexing and memory access order or something else? Container types? Prefetching?
Typical value of dimension_ is in the range of 3 to 10 (but can be 100, if value_type is mpfr or something else).
Isn't your (snippet from det())
for (size_type a = 1 + i; a < _dimension; ++a) {
vector & a_ = minor_[a - 1];
value_type const & ai_ = _matrix[a][i];
for (size_type b = 1 + i; b < _dimension; ++b) {
a_[b - 1] = ai_ * ri_[b];
}
}
for (size_type a = 1 + i; a < _dimension; ++a) {
vector const & a_ = minor_[a - 1];
vector & ra_ = _matrix[a];
for (size_type b = 1 + i; b < _dimension; ++b) {
ra_[b] -= a_[b - 1];
}
}
doing the same as
for (size_type a = 1 + i; a < _dimension; ++a) {
vector & ra_ = _matrix[a];
value_type ai_ = ra_[i];
for (size_type b = 1 + i; b < _dimension; ++b) {
ra_[b] -= ai_ * ri_[b];
}
}
without any need for minor_? Moreover, now the inner loop can easily be vectorised.
This question already has answers here:
How can I sort two vectors in the same way, with criteria that uses only one of the vectors?
(9 answers)
Closed 9 months ago.
I have this code here that has two arrays. It sorts arr[], so that the highest value will be in index 0. Now the second array arr1[] contains strings, I'd like the code to apply whatever changes where made to arr[] to arr1[]. So that arr[0] would return 6, while arr1[0] would return the string "d1". Notice how "d1" was at the same index as 6? After sorting I'd like the same values to still have their string counterparts.
How would I go about doing this?
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <functional>
using namespace std;
int main() {
int arr[ 5 ] = { 4, 1, 3, 6, 2 };
string arr1[ 5 ] = { "a1", "b1", "c1", "d1", "e1" };
std::sort( arr, arr + 5, std::greater< int >() );
cout << arr[0] << arr1[0] << endl;
system("pause");
}
Rather than sort the arrays, sort the indices. I.e., you have
int arr[5]={4,1,3,6,2}
string arr1[5]={"a1","b1","c1","d1","e1"};
and you make
int indices[5]={0,1,2,3,4};
now you make a sort indices comparator that looks like this (just and idea, you'll probably have to fix it a little)
class sort_indices
{
private:
int* mparr;
public:
sort_indices(int* parr) : mparr(parr) {}
bool operator()(int i, int j) const { return mparr[i]<mparr[j]; }
}
now you can use the stl sort
std::sort(indices, indices+5, sort_indices(arr));
when you're done, the indices array will be such that arr[indices[0]] is the first element. and likewise arr1[indices[0]] is the corresponding pair.
This is also a very useful trick when you're trying to sort a large data object, you don't need to move the data around at every swap, just the indices.
You need to combine them together and then sort the combined pair and then un-combine the pairs.
int arr[ 5 ] = { ... };
string arr1[ 5 ] = { ... };
pair<int, string> pairs[ 5 ];
for ( int i = 0; i < 5; ++i )
pairs[ i ] = make_pair( arr[ i ], arr1[ i ] );
sort( pairs.begin(), pairs.end() );
for ( int i = 0; i < 5; ++i )
{
arr[ i ] = pairs[ i ].first;
arr1[ i ] = pairs[ i ].second;
}
Really though, if arr and arr1 are related then they should be stored as the pair (or at least a custom struct) anyway. That way you don't need to use this as an intermediate step.
Write your own iterator and use STD:sort. It's easily coded in less than 50 lines without 3rd party libraries.
Swap function IS VERY IMPORTANT here.
#include <iostream>
#include <iterator> // std::iterator, std::input_iterator_tag
#include <algorithm>
using namespace std;
struct Tuple;
struct RefTuple;
#define TUPLE_COMMON_FUNC(C, D, E, F) \
C##::C## (Tuple& t) ##D \
C##::C## (RefTuple& t) ##D \
void C##::operator = (Tuple& t) ##E \
void C##::operator = (RefTuple& t) ##E \
bool C##::operator < (const Tuple& t) const ##F \
bool C##::operator < (const RefTuple& t) const ##F
#define ASSIGN_1 : i(t.i), j(t.j), s(t.s) {}
#define ASSIGN_2 { i = t.i; j = t.j; s = t.s; }
#define SORT_CRITERIA \
return (j < t.j) || (j == t.j && (i < t.i));
struct Tuple {
int i, j, s;
TUPLE_COMMON_FUNC(Tuple, ; , ; , ;)
};
struct RefTuple {
int &i, &j, &s;
RefTuple(int &x, int &y, int &z): i(x), j(y), s(z) {}
TUPLE_COMMON_FUNC(RefTuple, ; , ; , ;)
};
TUPLE_COMMON_FUNC(Tuple, ASSIGN_1, ASSIGN_2, {SORT_CRITERIA})
TUPLE_COMMON_FUNC(RefTuple, ASSIGN_1, ASSIGN_2, {SORT_CRITERIA})
void swap(RefTuple& t1, RefTuple& t2) {
t1.i ^= t2.i; t2.i ^= t1.i; t1.i ^= t2.i;
t1.j ^= t2.j; t2.j ^= t1.j; t1.j ^= t2.j;
t1.s ^= t2.s; t2.s ^= t1.s; t1.s ^= t2.s;
}
class IterTuple : public iterator<random_access_iterator_tag, Tuple> {
int *i, *j, *s, idx;
public:
IterTuple(int* x, int*y, int* z, int l) : i(x), j(y), s(z), idx(l) {}
IterTuple(const IterTuple& e) : i(e.i), j(e.j), s(e.s), idx(e.idx) {}
RefTuple operator*() { return RefTuple(i[idx], j[idx], s[idx]); }
IterTuple& operator ++ () { idx++; return *this; }
IterTuple& operator -- () { idx--; return *this; }
IterTuple operator ++ (int) { IterTuple tmp(*this); idx++; return tmp; }
IterTuple operator -- (int) { IterTuple tmp(*this); idx--; return tmp; }
int operator - (IterTuple& rhs) { return idx - rhs.idx; }
IterTuple operator + (int n) { IterTuple tmp(*this); tmp.idx += n; return tmp; }
IterTuple operator - (int n) { IterTuple tmp(*this); tmp.idx -= n; return tmp; }
bool operator==(const IterTuple& rhs) { return idx == rhs.idx; }
bool operator!=(const IterTuple& rhs) { return idx != rhs.idx; }
bool operator<(IterTuple& rhs) { return idx < rhs.idx; }
};
int Ai[10] = {0, 0, 2, 3, 2, 4, 1, 1, 4, 2};
int Aj[10] = {0, 2, 3, 4, 4, 4, 0, 1, 0, 2};
int Ax[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int main () {
IterTuple from(Ai, Aj, Ax, 0);
IterTuple until(Ai, Aj, Ax, 10);
sort(from, until);
for (IterTuple it = from; it != until; it++)
cout << (*it).i << ' ' << (*it).j << ' ' << (*it).s << '\n';
return 0;
}
I believe that writting your own QuickSort variant is simplier and the result will perform better then mapping custom iterators or array with indices.
QuickSort is not stable sort.
template<class A, class B> void QuickSort2Desc(A a[], B b[], int l, int r)
{
int i = l;
int j = r;
A v = a[(l + r) / 2];
do {
while (a[i] > v)i++;
while (v > a[j])j--;
if (i <= j)
{
std::swap(a[i], a[j]);
std::swap(b[i], b[j]);
i++;
j--;
};
} while (i <= j);
if (l < j)QuickSort2Desc(a, b, l, j);
if (i < r)QuickSort2Desc(a, b, i, r);
}