自己出的垃圾RMQ COGS-组卡组

1 篇文章 0 订阅
1 篇文章 0 订阅

【题目描述】

lemon最近迷上了优秀考智商的卡牌游戏(垃圾氪金)——游戏王。最为集换式卡牌鼻祖级的游戏,游戏王伴随了许多人的一生。在k社无节操地维护环境下,游戏王充满了无穷的可能性。但是lemon不知道如何组卡组(游戏王卡片出得太多了!lemon记不完),所以他找来了你来帮忙。现在他只想选一些怪兽卡作为自己的魂卡(们),(lemon:我又不是主角可以印卡逆天,攻防当然越高越好啦!!!)
有如下规则:
1.卡池有t张怪兽牌。
2.lemon需要q次查询,给你一个flag,
当flag=1时,每次查询区间[l,r]上攻击力最大的牌的攻击力a,
当flag=0时,每次查询区间[l,r]上防御力最大的牌的防御力d。

【输入格式】

输入第一行有两个整数t,q分别表示卡池中卡牌总数,与查询次数。
接下来t行,每行三个整数Ci,Ai,Di,分别表示卡片种类,卡片攻击力,卡片防御力。
接下来q行,每行三个整数fi,li,ri,f如题目描述中所述,表示查询类型,l,r表示查询区间,数据保证r>l,f只为1与0。

【输出格式】

输出共q行,每行一个整数,表示所询问的答案。
【样例输入】

6 2
1 4 9
1 4 9
2 3 4
3 4 5
4 5 20
5 30 5
1 2 3
0 1 5
【样例输出】

9
20
【提示】

对于30%的数据t≤100000,q≤100000
对于60%的数据t≤100000,q≤1000000
对于100%的数据t≤1000000,q≤1000000
所有数据均为非负整数,且都不大于2147483647。
数据保证合法,一道水题。
TANKS FOR YOUR VIEW
【来源】

lemonoil

就是一个RMQ,两种做法,
第一种是 O(n) 的RMQ,效率不错

#include <cstdio>
#include <cmath>
#include <vector>
#include <iostream>

using namespace std;

void read(int &x) {
    char c;bool flag = 0;
    while((c=getchar())<'0'||c>'9') flag |= (c=='-');
    x=c-'0';while((c=getchar())>='0'&&c<='9') x = (x<<3)+(x<<1)+c-'0';
    flag?x=-x:x;
}

#define N 1410000

int ans[N];

struct RMQ {
    struct Node { 
       int val,key,l,r;
       Node(int val = 0,int key = 0):val(val),key(key),l(-1),r(-1){} 
    }t[N<<1]; 

    int S[N],top,pos[N],sz;

    void dfs(int o) {
     if(o == -1) return;
     dfs(t[o].l);
     pos[t[o].key] = o;
     dfs(t[o].r);
   }

    void build(int a[],int n) {
       t[0] = Node(2147483647,n+1);
       S[top = 1] = 0; sz = 0;
       for (int i = 1; i <= n; i++) {
          t[++sz] = Node(a[i],i);
          int p = -1;
          while(t[S[top]].val <= t[sz].val) p = S[top--];
          t[sz].l = p;  t[S[top]].r = sz;
          S[++top] = sz;
       }
       dfs(0);
    }

   struct Que {int y,id;};
   int f[N],v[N],Lca[N];
   vector<Que> q[N];

   int fd(int x) {
     return x==f[x] ? x : f[x]=fd(f[x]);
   }

   void Tarjan(int x) {
       v[x] = 1; f[x] = x;
       for (int i = 0; i < 2; i++) {
         int to = i?t[x].l:t[x].r;
         if(to != -1 && !v[to]) {
            Tarjan(to);
            f[to] = x;          
         }
       }
       for (int i = 0; i < q[x].size(); i++) 
        if(v[q[x][i].y] && !Lca[q[x][i].id])
         Lca[q[x][i].id] = fd(q[x][i].y);
   }

   void slove (int m,int L[],int R[],int Cas[],int c) {
       for (int i = 1; i <= m; i++) {
           if(Cas[i] != c) continue;
           int l = pos[L[i]],r = pos[R[i]];
           q[l].push_back((Que){r,i});
           q[r].push_back((Que){l,i});
       }
       Tarjan(0);
       for (int i = 1; i <= m; i++) 
          if(Lca[i]) ans[i] = t[Lca[i]].val;
   }
}tx,ty;

int n,m,a[N],x[N],y[N],l[N],r[N],cas[N];

int main() {
    freopen("ygocrad.in","r",stdin);freopen("ygocrad.out","w",stdout);
    read(n); read(m);
    for (int i = 1,useless; i <= n; i++) read(useless),read(x[i]),read(y[i]);
    tx.build(x,n); ty.build(y,n);
    for (int i = 1; i <= m; i++) read(cas[i]),read(l[i]),read(r[i]);
    tx.slove(m,l,r,cas,1);
    ty.slove(m,l,r,cas,0);
    for (int i = 1; i <= m; i++) printf("%d\n",ans[i]);
    return 0;
}

其实这道题更多的是考高位寻址优化,详见洛可强大大的论文。

#include<cstdio>
#include<string>
#include<algorithm>
using namespace std;
const int MAX = 1000005;
const int LOGMAX  = 26;
int n,q,tot;
int st_maxf[LOGMAX][MAX],st_maxs[LOGMAX][MAX];  
void make_st(){
    register int i, j, k;  
    for(j=1;(1<<j)<=n;j++){
        k=1<<(j-1);
        for(i=0;i+k<n;i++){  
            st_maxf[j][i]=max(st_maxf[j-1][i],st_maxf[j-1][i+k]),
            st_maxs[j][i]=max(st_maxs[j-1][i],st_maxs[j-1][i+k]);  
        }
    }
}
int rmq(int a, int b, int flag){
    int dis=abs(b-a)+1;
    register int k;
    for(k=0;(1<<k)<=dis;++k);k--;
    if(flag){
        return max(st_maxf[k][a],st_maxf[k][b-(1<<k)+1]);  
    }else{
        return max(st_maxs[k][a],st_maxs[k][b-(1<<k)+1]);  
    }
} 
inline void read(int &res){
    static char ch;
    while((ch=getchar())<'0'||ch>'9');res=ch-48;
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;
}
int main(){
    //freopen("rmq.in","r",stdin);
    //freopen("rmq.out","w",stdout);
    freopen( "ygocrad.in", "r", stdin );
    freopen( "ygocrad.out", "w", stdout );
    read(n),read(q);
    register int i,x;
    for(i = 0; i<n; i++){
        read(x),read(st_maxf[0][i]),read(st_maxs[0][i]);  
    }
    make_st();
    for(i=0;i<q;i++){  
        int a,b,f;
        read(f),read(a),read(b);  
        printf("%d\n",rmq(a-1,b-1,f));  
    }
    return 0;
}

用上高位寻址优化的 O(nlogn2) 的RMQ竟然比 O(n) 的RMQ快,不想说话,下次用内存卡死你。。。。。。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值