8 - 7 训练赛- ACM-ICPC 2015 Changchun Preliminary Contest A优先队列G线段树区间最值H排序二叉树J大组合数取模卢卡斯+CRT

A
题意:邀请k个人来,m次开门操作,每次操作有x,y表示x个人来之后开门,这次开门能进来y个人。礼物最贵的先进,如果一样先来的先进。如果m次开门操作后还有没进来的,就都进来。给q个询问,第x个进来的人是谁。
思路:优先队列维护下。
Code:

#include <bits/stdc++.h>
#pragma comment(linker, “/STACK:1024000000,1024000000”)
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int AX = 150000+6;
const int maxn = 50000+6;
struct Node{
    char s[201];
    int id ;
    int v ;
    bool friend operator < ( const Node a , const Node &b ){
        return ( ( a.v == b.v && a.id > b.id) || ( a.v < b.v ) );
    }
}a[AX];

struct M{
    int num ;
    int t ; 
    bool friend operator < ( const M a , const M &b ){
        return ( a.t < b.t );
    }
}b[AX];
Node res[maxn];
int main(){
    int T;
    scanf("%d",&T);
    priority_queue<Node> que;
    while( T-- ){
        int k , m , q ;
        int tot = 0 ;
        while( !que.empty() ) que.pop();
        scanf("%d%d%d",&k,&m,&q);
        for( int i = 0 ; i < k;  i++ ){
            scanf("%s%d",a[i].s,&a[i].v);
            a[i].id = i ; 
        }
        for( int i = 0; i < m ; i++ ){
            scanf("%d%d",&b[i].t,&b[i].num);
        }
        sort( b , b + m );
        int cur = 0 ;
        for( int i = 0 ; i < m ; i++ ){
            while( cur < b[i].t ){
                que.push( a[cur++] );
            }
            int tmp = b[i].num;
            while( !que.empty() && tmp ){
                res[tot++] = que.top();
                que.pop();
                tmp -- ;
            }
        }

        while( cur < k ){
            que.push(a[cur++]);
        }
        while( !que.empty() ){
            res[tot++] = que.top();
            que.pop();
        }

        int x ; 
        for( int i = 0 ; i < q - 1 ; i++ ){
            scanf("%d",&x);
            printf("%s ",res[x-1].s);
        }
        scanf("%d",&x);
        printf("%s\n",res[x-1].s);
    }   
    return 0 ;
}

G

题意:区间最值。
思路:线段树裸题。
Code:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define LL long long 
using namespace std;
const int AX = 1e6+6;
LL a[AX<<2];
void pushUp( int rt ){
    a[rt] = max( a[rt<<1] , a[rt<<1|1] );
}

void build_tree(int l,int r ,int rt)    {      
    if(l == r){
        scanf("%ld",&a[rt]);
        return;
    }
    int mid = (l+r) >> 1;
    build_tree(l,mid,rt<<1);
    build_tree(mid+1,r,rt<<1|1);
    pushUp(rt);
}
int query_MAX( int L , int R , int l , int r , int rt ){
    if( L <= l && R >= r ) return a[rt];
    int ans = -INF;
    int mid = ( l + r ) >> 1;
    if( L <= mid) ans = max( ans , query_MAX( L , R , l , mid , rt << 1 ) ) ;
    if( R > mid ) ans = max( ans , query_MAX( L , R , mid + 1 , r , rt << 1 | 1 ) ) ;
    return ans ;
}

int main(){
    int n , m;
    int T;
    scanf("%d",&T);
    while( T-- ){
        memset( a , 0 , sizeof(a) );
        scanf("%d",&n);
        build_tree( 1 , n , 1 );
        int q;
        scanf("%d",&q);
        int l ,r ;
        while( q-- ){
            scanf("%d%d",&l,&r);
            printf("%d\n",query_MAX(l,r,1,n,1));
        }
    }

    return 0 ;
}

H
题意:给一个序列从根节点开始建树,比一个节点大的就放在E,小的就放在W方向,问从根节点开始到给定节点x,路径是什么。
思路:排序二叉树
Code:

#include <bits/stdc++.h>
using namespace std;
const int AX = 1e3+66;
int a[AX];
struct Node{
    Node *l ;
    Node *r ;
    int v ; 
    bool vis ;
    Node( ){
        l = NULL; r = NULL; vis = false; v = 0;
    }
} ;
Node *root ;

void insert( Node *t , int x ){
    if( !t -> v ) t -> v = x;
    else if( x < t -> v ){
        if( !t -> l ) t -> l = new Node;
        insert( t -> l , x );
    }else{
        if( !t -> r ) t -> r = new Node;
        insert( t -> r , x );
    }
}

void print( Node *t , int x ){
    if( t -> v == x ){
        return;
    }
    if( x < t -> v ){
        printf("E");
        print( t -> l , x );
    }else{
        printf("W");
        print( t -> r , x );
    }
}

int main(){
      int T;
    scanf("%d",&T);
    while( T-- ){
        int n;
        root = new Node;
        scanf("%d",&n);
        for (int i = 1 ; i <= n ; i ++ ) {
            scanf("%d",&a[i]);
            insert(root,a[i]);
        }
        int q;
        scanf("%d",&q);
        int x ;
        for( int i = 0 ; i < q ; i++ ){
            scanf("%d",&x);
            if( x != a[1] ){
                print( root , x );
            }
            if( i != q - 1 ) printf("\n");
        }
        if( T ) printf("\n");
    }
    return 0;
}

J
题意:求C( n ,m ) % mod ( mod = p1 * p2 * p3 ** pk ) ( k < = 10 ) 且pi互不相同。
思路:大组合数取模: 卢卡斯定理+CRT。
C( n, m ) % mod 相当于求 C(n,m) % pi (1<=i<=k) 再用CRT合并。

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD =  1e9+7;
const int MAXN = 2e5+10;
#define LL long long
LL qmul(LL a,LL p,LL m){
    LL tmp = 0;
    while(p){
        if(1&p) tmp = (tmp+a)%m;
        a = (a+a)%m;
        p>>=1;
    }
    return tmp;
}
void exgcd(LL a,LL b,LL &x,LL &y,LL &d){
    if(!b) d=a,x = 1,y=0;
    else exgcd(b,a%b,y,x,d),y-=(a/b)*x;
}
LL inv(LL a,LL p){
    LL x,y,d;
    exgcd(a,p,x,y,d);
    return d==1?(x+p)%p:-1;
}
LL fat(LL x,LL p){
    LL ans = 1;
    for( int i = 2 ; i <= x ; i ++ ) ans = ( ans * i ) % p;
    return ans;
}
LL c(LL n,LL m,LL p){
    if (m < 0 || m > n) return 0; 
    return fat(n,p)*inv(fat(m,p),p)%p*inv(fat(n-m,p),p)%p;
}
LL crt(LL *a,LL *m,int n){
    LL M = 1,res = 0;
    for( int i = 0 ; i < n ; i++ ) M*=m[i];
    for( int i = 0 ; i < n ; i++ ){
        LL w = M/m[i];
        res = (res+qmul(w*inv(w,m[i]),a[i],M))%M;
    }
    return (res+M)%M;
}
LL Lucas(LL n,LL m,LL p){
    return m?Lucas(n/p,m/p,p)*c(n%p,m%p,p)%p:1;
}
int main(){
    LL n,m;
    LL p[15];
    LL a[15];
    int T,k;
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld%d",&n,&m,&k);
        for( int i = 0 ; i < k ; i++ ){
            scanf("%lld",&p[i]);
        }
        for( int i = 0 ; i < k ; i++ ){
            a[i] = Lucas( n , m , p[i] );
        }
        printf("%lld\n",crt(a,p,k));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/FrankAx/article/details/81488996