码迷,mamicode.com
首页 > 其他好文 > 详细

[题解]CodeForces878 D - Magic Breeding

时间:2019-11-05 16:50:33      阅读:96      评论:0      收藏:0      [点我收藏+]

标签:gic   using   使用   题解   inline   long   while   ORC   bre   

题目描述

\(K\)只神奇的生物,每一只有\(n\)个属性。Q次操作:

  1. \((1,x,y)\):产生一只新的生物,每一个属性为\(x\)\(y\)的该属性的最大值
  2. \((2,x,y)\):产生一只新的生物,每一个属性为\(x\)\(y\)的该属性的最小值
  3. \((3,x,y)\):查询第\(x\)只生物的\(y\)属性

每一次新生物的编号为最小的没有被使用的正整数

\(1\leq K \leq 12,1\leq n,Q\leq 10^5\)

分析

感觉这题只可意会比较难讲清楚qwq

首先,每一只新生物的属性来自于最开始的\(K\)只生物,这非常显然

官方题解里面说的是只可能有\(2^K\)种情况,把每一种用一个\(K\)位二进制数来表示,第\(i\)位为\(1\)表示这种生物的每一个属性都小于等于第\(i\)种生物的对应属性。

我们对于每一种生物存一个\(2^K\)位的状态,记为 \(f\),表示这个生物的每一个属性为(((\(1\)位上的情况)的这种属性)中最大的)。具体地:

假如我们要求第\(x\)个生物的第\(y\)种属性,那么我们按照y属性从大到小的顺序枚举每一种最开始的生物,并把它或到\(mask\)中,如果\(x\)生物的第\(mask\)位为1,那么答案就是当前生物的这个属性

        int now=0;
        rep(i,1,K){
            now|=(1<<(id[y][i]-1));
            if(f[x][now]==1){
                printf("%d\n",a[id[y][i]][y]);
                return;
            }
        }
  • 对于1操作:每一个属性只需要\(\leq\)x的这个属性\(\leq\)y的这个属性,所以新的生物的状态就是\(f[x]|f[y]\)

  • 对于2操作:每一个属性都要\(\leq\)x的这个属性\(\leq\)y的这个属性,新状态为\(f[x]\)&\(f[y]\)

算了还是毛估估吧

代码

#include<bits/stdc++.h>
#define rep(X,A,B) for(int X=A;X<=B;X++)
#define tep(X,A,B) for(int X=A;X>=B;X--)
#define LL long long
#define DB double
const int KK=15;
const int N=100015;
const int MX=1<<13;//!!!!!!!!!
using namespace std;
 
int n,K,Q,tot,hlp,maxn;
int a[KK][N],id[N][KK];
bitset<MX>f[N];
 
void READ(){
    scanf("%d%d%d",&n,&K,&Q);
    rep(i,1,K)rep(j,1,n)scanf("%d",&a[i][j]);
    tot=K;
}
 
int cmp(int x,int y){
    return a[x][hlp]>a[y][hlp];
}
 
void INIT(){
    maxn=(1<<K)-1;
    rep(i,1,K){
        rep(num,0,maxn){
            if(num&(1<<(i-1)))f[i][num]=1;
        }
    }
    rep(i,1,n){
        rep(j,1,K)id[i][j]=j;
        hlp=i;
        sort(id[i]+1,id[i]+K+1,cmp);
    }
}
 
void SOLVE(){
    int pd,x,y;
    scanf("%d%d%d",&pd,&x,&y);
    if(pd==1)f[++tot]=f[x]|f[y];
    if(pd==2)f[++tot]=f[x]&f[y];
    if(pd==3){
        int now=0;
        rep(i,1,K){
            now|=(1<<(id[y][i]-1));
            if(f[x][now]==1){
                printf("%d\n",a[id[y][i]][y]);
                return;
            }
        }
    }
}
 
int main(){
    READ();
    INIT();
    while(Q--)SOLVE();
    return 0;
}

[题解]CodeForces878 D - Magic Breeding

标签:gic   using   使用   题解   inline   long   while   ORC   bre   

原文地址:https://www.cnblogs.com/SCL123/p/11799263.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!