@gym - 100591D@ Fox Rocks


@description@

Given N points and the unidirectional path P Ai -> Bi, Ri stones have each road (guaranteed \ (0 \ le \ lfloor \ frac {Bi} {4} \ rfloor- \ lfloor \ frac {Ai} . 4} {\ rfloor \ Le. 1 \) ).

The next day there is an interrogation D per day, divided into three categories:
(1) a given X, Y, Z, the construction of a X -> Y and Z stones of roads.
(2) given X, Y, demolition X -> Y of the original road.
(3) query from X to start random walk (from the side of its moderate probability selected a stone, and that edge to go) the probability of Y can be reached.

link.

@solution@

A cup of tea, a pack of cigarettes, an essay tune day.

If we four consecutive points as a block, even where the edge should be connected in the block side edges connected a downwardly + block.
If you do violence with probability dp, can start from the starting point X, Y recursive back to the block where, Gaussian elimination within a block of each block.

This process can be accelerated with apparent segment tree: each node [l, r] from the random walk maintain the i-th point of the l-th block, the first arrival of block r is the j th block of r points probability p [i] [j].
Segment tree merge process is a Gaussian elimination.
Last modification made at the block where Y a Gaussian elimination, from where the block Y i-th point to the j-th point of the probability q [i] [j].

however. . . There is a small problem.
Dp is the probability of the general form: a plurality of fixed termination state, to ensure that each point can be reached for terminating state, and each side has a certain probability of metastasis.
Defined probability dp [i] represents the desired state has been reached to terminate, the dp [i] or migrate to the point that it can be reached, either directly to the final state.

This question has terminated and the state "not out degree", "Y arrival", "reaching the next block of Y", and a "Y can not reach into the ring of a."
The first three can be expressed by the formula dp transfer, but the last one and can not be expressed directly. . .
Either by a simple method of determining dfs, or there is a special determination: if the main diagonal Gaussian Elimination = 0, then the last case necessarily occur. At this time, to directly modify the equation xi = 0 to form.

@accepted code@

#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;

const int MAXN = 50000;
const double EPS = 1E-9;

double dcmp(double x) {return fabs(x) <= EPS ? 0 : (x > 0 ? 1 : -1);}

struct node{double a[4][4];};

int K;

double d[MAXN + 5];
node f[MAXN + 5], g[MAXN + 5], h[MAXN + 5];

double M[100][100];
void gauss(int n, int m) {
    int r = 0, c = 0;
    while( r < n && c < m ) {
        if( dcmp(M[r][c]) ) {
            double k = M[r][c];
            for(int j=c;j<m;j++)
                M[r][j] /= k;
            for(int i=0;i<n;i++) {
                if( i == r ) continue;
                k = M[i][c];
                for(int j=c;j<m;j++)
                    M[i][j] -= k*M[r][j];
            }
            r++;
        }
        else {
            for(int j=c;j<m;j++)
                M[r][j] = 0;
            M[r][c] = 1;
            r++;
        }
        c++;
    }
}

void get(int x, node &p) {
    for(int t=0;t<4;t++) {
        for(int r=0;r<4;r++)
            for(int c=0;c<4;c++)
                M[r][c] = 0;
        for(int r=0;r<4;r++) {
            if( r == t ) {
                for(int c=0;c<4;c++)
                    M[r][c] = (r == c);
                M[r][4] = 1;
            }
            else {
                int k = 4*x + r;
                for(int c=0;c<=4;c++)
                    M[r][c] = (r == c);
                if( d[k] == 0 ) continue;
                for(int c=0;c<4;c++)
                    M[r][c] -= f[x].a[r][c] / d[k];
            }
        }
        gauss(4, 4+1);
        for(int s=0;s<4;s++) 
            p.a[s][t] = M[s][4];
    }
}

struct segtree{
    #define lch (x << 1)
    #define rch (x << 1 | 1)
    
    int le[4*MAXN + 5], ri[4*MAXN + 5]; node h[4*MAXN + 5];
    void merge(const node &f1, const node &f2, node &f3, int m) {
        for(int i=0;i<4;i++)
            for(int j=0;j<4;j++)
                f3.a[i][j] = 0;
        for(int t=0;t<4;t++) {
            for(int r=0;r<4;r++) {
                int k = 4*m + r;
                for(int c=0;c<4;c++) {
                    if( d[k] ) M[r][c] = (r == c) - f[m].a[r][c]/d[k];
                    else M[r][c] = (r == c);
                }
                if( r == t ) M[r][4] = 1;
                else M[r][4] = 0;
            }
            gauss(4, 5);
            int k = 4*m + t;
            if( d[k] ) {
                double a[4] = {}, b[4] = {};
                for(int p=0;p<4;p++)
                    for(int s=0;s<4;s++)
                        a[p] += M[s][4]*f1.a[p][s];
                for(int q=0;q<4;q++)
                    for(int x=0;x<4;x++)
                        b[q] += g[m].a[t][x]/d[k]*f2.a[x][q];
                for(int p=0;p<4;p++)
                    for(int q=0;q<4;q++)
                        f3.a[p][q] += a[p]*b[q];
            //f3.a[p][q] += M[s][4]*div(g[m].a[t][x], d[k])*f1.a[p][s]*f2.a[x][q];
            }
        }
    }
    void pushup(int x) {
        int m = (le[x] + ri[x]) >> 1;
        merge(h[lch], h[rch], h[x], m);
    }
    void build(int x, int l, int r) {
        le[x] = l, ri[x] = r;
        if( l == r ) {
            for(int i=0;i<4;i++)
                for(int j=0;j<4;j++)
                    h[x].a[i][j] = (i == j);
            return ;
        }
        int m = (le[x] + ri[x]) >> 1;
        build(lch, l, m), build(rch, m + 1, r);
        pushup(x);
    }
    void update(int x, int p) {
        if( le[x] == ri[x] ) return ;
        int m = (le[x] + ri[x]) >> 1;
        if( p <= m ) update(lch, p);
        else update(rch, p);
        pushup(x);
    }
    node query(int x, int ql, int qr) {
        if( ql <= le[x] && ri[x] <= qr )
            return h[x];
        int m = (le[x] + ri[x]) >> 1;
        if( qr <= m ) return query(lch, ql, qr);
        else if( ql > m ) return query(rch, ql, qr);
        else {
            node a = query(lch, ql, qr), b = query(rch, ql, qr), c;
            merge(a, b, c, m); return c;
        }
    }
}T;


void update(int A, int B, double R) {
    d[A] += R;
    if( A / 4 == B / 4 ) f[A/4].a[A%4][B%4] += R;
    else g[A/4].a[A%4][B%4] += R;
    get(A/4, h[A/4]), T.update(1, A/4);
}
void remove(int A, int B) {
    if( A / 4 == B / 4 ) update(A, B, -f[A/4].a[A%4][B%4]);
    else update(A, B, -g[A/4].a[A%4][B%4]);
}

int N, P, D;

void solve() {
    scanf("%d%d%d", &N, &P, &D), K = N, N = (N + 3) / 4;
    for(int i=0;i<4*N;i++) d[i] = 0;
    for(int i=0;i<N;i++)
        for(int j=0;j<4;j++)
            for(int k=0;k<4;k++)
                f[i].a[j][k] = g[i].a[j][k] = 0;
    for(int i=1;i<=P;i++) {
        int A, B, R; scanf("%d%d%d", &A, &B, &R);
        d[A] += R;
        int del = B - (A/4*4);
        if( del < 4 ) f[A/4].a[A%4][del] += R;
        else g[A/4].a[A%4][del-4] += R;
    }
    for(int i=0;i<N;i++)
        get(i, h[i]);
    T.build(1, 0, N - 1);
    for(int i=1;i<=D;i++) {
        int op; scanf("%d", &op);
        if( op == 1 ) {
            int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z);
            update(X, Y, Z);
        }
        else if( op == 2 ) {
            int X, Y; scanf("%d%d", &X, &Y);
            remove(X, Y);
        }
        else {
            int X, Y; scanf("%d%d", &X, &Y);
            if( X / 4 <= Y / 4 ) {
                node p = T.query(1, X / 4, Y / 4);
                double ans = 0;
                for(int i=0;i<4;i++)
                    ans += p.a[X%4][i] * h[Y/4].a[i][Y%4];
                printf(" %.6f", ans);
            }
            else printf(" %.6f", 0.0);
        }
    }
}

int main() {
//  freopen("data.in", "r", stdin);
//  freopen("data.out", "w", stdout);
    int t; scanf("%d", &t);
    for(int i=1;i<=t;i++)
        printf("Case #%d:", i), solve(), puts("");
}
/*
5
8 0 10
1 0 1 1
1 1 2 1
1 2 3 1
3 0 3
1 0 4 1
3 0 3
1 0 3 1
3 0 3
2 1 2
3 0 3

4 4 10
0 1 1
1 0 1
1 2 1
0 3 1
3 0 2
2 0 1
1 0 1 2
3 0 2
2 0 1
1 0 1 3
3 0 2
2 0 1
1 0 1 4
3 0 2

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

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

12 5 7
0 4 1
4 8 1
0 1 1
1 2 1
2 3 1
3 0 8
1 1 4 1
3 0 8
1 2 4 1
3 0 8
1 3 4 1
3 0 8
*/

@details@

Do question the mentality of:

"Woc What is disgusting problem, forget the idea quite simple, first write to say"
"woc how could not pass the sample, woc I misread the title to it can not block that Wang Qianmian run. Anyway, all right also to simple change direction "
" WOC how card on the second data, woc it turned out to be the WA! this is not how to do it is the accuracy issue "
" (to steal a correct code, build a little big data)! how can there nan this kind of thing, seems to have debugging "
" it WOC Gaussian elimination to eliminate even the line did not?! Is ... "

Then we discovered the problem.

Guess you like

Origin www.cnblogs.com/Tiw-Air-OAO/p/12178224.html