机房模拟赛 2017年9月27日

这里写图片描述
这里写图片描述
这里写图片描述
今天的题显然是mhy出的233


t1裸莫队,t3裸平衡树或者堆,t2到现在都还不会,说是什么可持久化trie并且带合并,我好菜啊


#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 100000 + 10;
int n, m, block, cnt[ MAXN * 2 ] ;
long long a[ MAXN * 2 ];
struct Q { int l, r, id, blo; long long ans; }q[ MAXN * 2 ];
bool cmp( const Q &a, const Q &b ) {
    if( a.blo != b.blo ) return a.blo < b.blo;
    if( a.r != b.r )     return a.r < b.r;
    return a.l < b.l;
}
void MosAlgorithm( ) {
    long long ans = 0;
    int l = 1, r = 0;
    for( register int i = 1; i <= m; i++ ) {
        while( l < q[i].l ) {
            cnt[a[l]]--;
            if( cnt[a[l]] == 2 ) ans -= 3LL * a[l];
            else if( cnt[a[l]] == 1 ) ans += a[l];
            else ans -= a[l];
            l++;
        }
        while( l > q[i].l ) {
            l--;
            cnt[a[l]]++;
            if( cnt[a[l]] == 2 ) ans -= a[l];
            else if( cnt[a[l]] == 3 ) ans += 3LL * a[l]; 
            else ans += a[l];
        }
        while( r < q[i].r ) {
            r++;
            cnt[a[r]]++;
            if( cnt[a[r]] == 2 ) ans -= a[r];
            else if( cnt[a[r]] == 3 ) ans += 3LL * a[r];
            else ans += a[r];
        }
        while( r > q[i].r ) {
            cnt[a[r]]--;
            if( cnt[a[r]] == 2 ) ans -= 3LL * a[r];
            else if( cnt[a[r]] == 1 ) ans += a[r];
            else ans -= a[r];
            r--;
        }
        q[q[i].id].ans = ans;
    }
    for( register int i = 1; i <= m; i++ ) printf( "%I64d\n", q[i].ans );
} 
int main( ) {
    scanf( "%d%d", &n, &m ); int block = sqrt(n);
    for( register int i = 1; i <= n; i++ ) scanf( "%I64d", &a[i] ); 
    for( register int i = 1; i <= m; i++ ) { 
        scanf( "%d%d", &q[i].l, &q[i].r ); 
        q[i].id = i; 
        q[i].blo = ( q[i].l - 1 ) / block + 1;
    } 
    sort( q + 1, q + m + 1, cmp );
    MosAlgorithm();
    return 0;
}
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
using namespace std;
const int mod = 1e9 + 7;
const int MAXN = 1e6 + 10;
int f[MAXN], M[MAXN], a, b, c, d, sz, n;
long long ans;
int root;
struct Tree{ int lson, rson, rnd, sz, wei; int num; }tree[ MAXN * 4 ];
void update( int rt ) { tree[rt].sz = tree[tree[rt].lson].sz + tree[tree[rt].rson].sz + tree[rt].wei; }
void Right_Rotate( int &k ) {
    int t = tree[k].lson;
    tree[k].lson = tree[t].rson;
    tree[t].rson = k;
    tree[t].sz = tree[k].sz;
    update(k);
    k = t;
}
void Left_Rotate( int &k ) {
    int t = tree[k].rson;
    tree[k].rson = tree[t].lson;
    tree[t].lson = k;
    tree[t].sz = tree[k].sz;
    update(k);
    k = t;
}
void insert( int &k, int x ) {
    if( k == 0 ) {
        k = ++ sz;
        tree[k].num = x;
        tree[k].rnd = rand();
        tree[k].sz = tree[k].wei = 1;
        return;
    }
    tree[k].sz++;
    if( x == tree[k].num ){ tree[k].wei++; return; }
    else if( x < tree[k].num ) {
        insert( tree[k].lson, x );
        if( tree[tree[k].lson].rnd < tree[k].rnd ) Right_Rotate(k);
    } else {
        insert( tree[k].rson, x );
        if( tree[tree[k].rson].rnd < tree[k].rnd ) Left_Rotate(k);
    }
}
long long find( int k, int rnk ) {
    if( rnk >= tree[tree[k].lson].sz + 1 && rnk <= tree[tree[k].lson].sz + tree[k].wei ) return tree[k].num;
    else if( rnk <= tree[tree[k].lson].sz ) return find( tree[k].lson, rnk );
    else return find( tree[k].rson, rnk - tree[tree[k].lson].sz - tree[k].wei );
}
int main( ) {
    scanf( "%d%d%d%d", &a, &b, &c, &n );
    f[1] = 1;
    insert( root, f[1] ); M[1] = 0;
    ans = 1LL;
    for( register int i = 2; i <= n; i++ ) {
        int kth = ( i - 1 ) / 2;
        if( ( i - 1 ) % 2 == 1 ) kth++;
        M[i] = find( root, kth ); 
        f[i] = ( 1LL * M[i] * a + b * i + c ) % mod;
        ans += 1LL * f[i];
        insert( root, f[i] );
    }
    printf( "%I64d\n", ans );
}

treap要挂掉两个点,没有办法,太慢了,heap会好很多
今天多亏t1写了对拍,要不然就发现不了一个致命错误啦233


如果有哪位dalao愿意赐教t2的,不胜感激233,联系邮箱

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值