2014.7.29 - 多校3

http://blog.sina.com.cn/s/blog_6bddecdc0102uyp3.html


hdu-4889-Scary Path Finding Algorithm

problem

think

构造。按照题解的构造方法写了一个。想不出来啊。

code

int bit[100];
long long spfa_slf(int C, int nn) {
    int n,m;
    n = nn*2+1;
    m = n*3;
    vector<pair<int,int> > edges[111];
    for(int i = 1; i <= nn; ++i){
    //cout<<i<<"   "<<C<<"   "<<nn<<endl;
        int id1 = 2*i - 1;
        int id2 = 2*i;
        int id3 = 2*i+1;
        int x, y, w;
        x = id1;
        y = id2;
        w = 0;
        //cout<<x<<"  "<<y<<"  "<<w<<endl;
        edges[x].push_back(make_pair(y,-w));
        x = id1;
        y = id3;
        w = bit[nn-i];
        //cout<<x<<"  "<<y<<"  "<<w<<endl;
        edges[x].push_back(make_pair(y,-w));
        x = id2;
        y = id3;
        w = bit[nn-i+1];
        //cout<<x<<"  "<<y<<"  "<<w<<endl;
        edges[x].push_back(make_pair(y,-w));
    }
    deque<int> q;
    vector<long long> dist(n+1, ~0ULL>>1);
    vector<bool> inQueue(n+1, false);
    dist[1] = 0;
    q.push_back(1);
    inQueue[1] = true;

    int doge = 0;
    while(!q.empty()) {
        int x = q.front(); q.pop_front();
        //cout<<x<<endl;
        //cout<<"+++++++  "<<q.size()<<"    "<<doge<<"  "<<C<<endl;
        if(doge++ > C) {
            puts("doge");
            //cout<<endl<<"          "<<C<<endl;
            return 233;
        }
        for(vector<pair<int,int> >::iterator it = edges[x].begin();
        it != edges[x].end();++it) {
            int y = it->first;
            int w = it->second;
            if(dist[y] > dist[x] + w) {
                dist[y] = dist[x] + w;
                if(!inQueue[y]) {
                    inQueue[y] = true;
                    if(!q.empty() && dist[y] > dist[q.front()])
                        q.push_back(y);
                    else
                        q.push_front(y);
                }
            }
        }
        inQueue[x] = false;
    }
    return dist[n];
}


int main(){
    int C;
    bit[0] = 1;
    for(int i = 1; i <= 31; ++i) bit[i] = bit[i-1] * 2;
    bit[0] = 0;
    while(scanf("%d", &C) != EOF){
        if(C < 0){
            puts("2 1");
            puts("1 2 1");
            continue;
        }
        ++C;
        int n = 1;
        int N = 2;
        while(N < C){
            ++n;
            N *= 2;
        }
        printf("%d %d\n", 2*n+1, 3*n);
        for(int i = 1; i <= n; ++i){
            int id1 = 2*i - 1;
            int id2 = 2*i;
            int id3 = 2*i+1;
            printf("%d %d %d\n", id1, id2, 0);
            printf("%d %d %d\n", id1, id3, -bit[n-i]);
            printf("%d %d %d\n", id2, id3, -bit[n-i+1]);
        }
        //spfa_slf(C, n);
    }
    return 0;
}


hdu-4893-Wow! Such Sequence!

problem

n个点,m个操作。

1 x y,第x个数加y

2 x y,第x个数到第y个数的和

3 x y,第x个数到第y个数分别变成和他差的绝对值最小的那个fib数,如果前后两个一样变成前一个。

think

线段树。存两个值,一个是实际值,一个是fib值。

code

const int N = 111111;
ll fb[10000];
ll t[N<<2][2];
int L[N<<2], R[N<<2];
int op[N<<2];//0 1 2
int n, m;
void gao() {
    fb[0] = 1, fb[1] = 1;
    for (int i = 2; i <= 91; i++) fb[i] = fb[i - 1] + fb[i - 2];//, cout<<fb[i]<<endl;
}

void build(int l, int r, int k){
    L[k] = l;
    R[k] = r;
    op[k] = 0;
    t[k][0] = 0;
    t[k][1] = r - l + 1;
    if(l == r) return;
    int mid = ( l + r) >> 1;
    build(l, mid, k<<1);
    build(mid+1, r, k<<1|1);
}

void down(int k){
    if(op[k] == 1){
        op[k<<1] = 1;
        t[k<<1][0] = t[k<<1][1];
        op[k<<1|1] = 1;
        t[k<<1|1][0] = t[k<<1|1][1];
    }
    op[k] = 0;
}

void up(int k){
    op[k] = 0;
    for(int i = 0; i <= 1; ++i) t[k][i] = t[k<<1][i] + t[k<<1|1][i];
}

void update1(int a, int k, ll d){
    if(a== L[k] && a == R[k]){
        ll tmp = t[k][0] + d;
        t[k][0] = tmp;
        int fuck = lower_bound(fb, fb + 92, tmp) - fb;
        if (fb[fuck] == tmp) t[k][1] = fb[fuck];
        else if (fuck == 0) t[k][1] = 1;
        else {
            if (tmp - fb[fuck - 1] > fb[fuck] - tmp) t[k][1] = fb[fuck];
            else t[k][1] = fb[fuck - 1];
        }
        op[k] = 0;
        return ;
    }
    down(k);
    int mid = (L[k] + R[k]) >> 1;
    if(a<=mid) update1(a, k<<1, d);
    else update1(a, k<<1|1, d);
    up(k);
}

void update2(int l, int r, int k){
    if(l == L[k] && r == R[k]){
        op[k] = 1;
        t[k][0] = t[k][1];
        return ;
    }
    down(k);
    int mid = (L[k] + R[k]) >> 1;
    if(r <= mid) update2(l, r, k<<1);
    else if(l > mid) update2(l, r, k<<1|1);
    else{
        update2(l, mid, k<<1);
        update2(mid+1, r, k<<1|1);
    }
    up(k);
}

ll query(int l, int r, int k){
    if(l == L[k] && r == R[k]) return t[k][0];
    down(k);
    int mid = (L[k] + R[k]) >> 1;
    if(r <= mid) return query(l, r, k<<1);
    else if(l > mid) return query(l, r, k<<1|1);
    else return (query(l, mid, k<<1) + query(mid+1, r, k<<1|1));
}

int main () {
    gao();
    while(scanf("%d%d", &n, &m) != EOF){
        build(1, n, 1);
        for(int i = 0; i < m; ++i){
            int oo, l, r;
            ll d;
            scanf("%d%d", &oo, &l);
            if(oo == 1){
                scanf("%I64d", &d);
                update1(l, 1, d);
            } else if(oo == 2){
                scanf("%d", &r);
                printf("%I64d\n", query(l, r, 1));
            } else {
                scanf("%d", &r);
                update2(l, r, 1);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值