zoukankan      html  css  js  c++  java
  • D

    There are nn people at the round gaming table. Each of them has a set of cards. Every card contains some number xx. Players make turns consecutively, one after another, starting from the player number 1. A player in his turn can either skip his turn (to pass), or put (and leave on the table) a card with a number that is strictly greater than the previously played last number. No more than kk players in a row can pass the turn. All players know the numbers written on the other players cards and always play optimally. Help gamblers to assemble an increasing sequence of maximum length.

    Input

    The first line contains two numbers nn and kk — the number of players and the maximum possible amount of turn skipping in a row.

    The next nn lines contain the description of the cards players have in their hands. The first number in the mimi is the number of cards the current player has in his hand. The following space separated miminumbers represent the written on the cards numbers xx.

    0mi1050≤∑mi≤105
    1n1051≤n≤105
    0k<n0≤k<n
    0x1090≤x≤109

    Output

    In the first line print the single number — the length of the maximum sequence. In the next lines print two space separated numbers: the player index number and the number written on the card he played. If several solutions exist, output any of them.

    Example

    Input
    3 1
    4 1 10 12 20
    2 11 21
    4 3 5 15 22
    
    Output
    9
    1 1
    3 3
    1 10
    2 11
    1 12
    3 15
    1 20
    2 21
    3 22

    #include <bits/stdc++.h>
    #define ll long long
    #define ull unsigned long long
    #define met(a, b) memset(a, b, sizeof(a))
    #define rep(i, a, b) for(int i = a; i <= b; i++)
    #define bep(i, a, b) for(int i = a; i >= b; i--)
    #define lowbit(x) (x&(-x))
    #define MID (l + r) / 2
    #define ls pos*2
    #define rs pos*2+1
    #define pb push_back
    #define ios() ios::sync_with_stdio(0)
     
    using namespace std;
    typedef pair<int,int>pi;
    const int maxn = 1e5 + 1010;
    const int inf = 0x3f3f3f3f;
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    const ll mod = 1e9 + 7;
    
    struct node{
      int id,x;
      bool operator < (const node & w)const{
        return x < w.x || (x == w.x && id < w.id);
      }
    }arr[maxn];
    pi dp[maxn],tree[maxn<<2];
    void pushup(int rt){
      tree[rt] = max(tree[rt*2],tree[rt*2+1]);
    }
    void build(int l,int r,int rt){
      if(l == r){
        tree[rt] = pi(0,-1);
        return ;
      }
      int mid = (l + r) / 2;
      build(l,mid,rt*2);
      build(mid + 1,r,rt*2+1);
      pushup(rt);
    }
    pi query(int L,int R,int l,int r,int rt){//询问[L,R]内长度最长的上升子序列节点
      if(L > R)return pi(0,-1);
      if(L <= l && r <= R){
        return tree[rt];
      }
      int mid = (l + r) / 2;
      pi ans = pi(0,-1);
      if(L <= mid)ans = max(ans,query(L,R,l,mid,rt*2));
      if(R >  mid)ans = max(ans,query(L,R,mid+1,r,rt*2+1));
      return ans;
    }
    void update(int pos,pi val,int l,int r,int rt){//pos位置更改最优值(和自身取最优值)
      if(l == r){
        tree[rt] = max(tree[rt],val);
        return ;
      }
      int mid = (l + r) / 2;
      if(pos <= mid)update(pos,val,l,mid,rt*2);
      else update(pos,val,mid+1,r,rt*2+1);
      pushup(rt);
    }
    void dfs(int u,int dep){//dfs寻找路径,dp[u].second 代表下一个下标是几
      if(u == -1){
        cout << dep << endl;
        return ;
      }
      dfs(dp[u].second,dep+1);
      cout << arr[u].id << ' ' << arr[u].x << endl;
    }
    int main()
    {
      int n,k,top = 0;
      cin >> n >> k;
      build(1,n,1);
      rep(i,1,n){
        int m;
        cin >> m;
        rep(j,1,m){
          int x;
          cin >> x;
          arr[++top] = (node){i,x};
        }
      }
      sort(arr+1,arr+1+top);
      int i;
      for(i = 1;i <= top;){
        for(int j = i;j <= top;j++){//一个值的数据有多个的话,处理完,先不更新,因为题目保证严格递增
          if(arr[i].x != arr[j].x)break;
          int id = arr[j].id;
          int pos = ((id - k - 2) % n + n) % n + 1;//最多可跳过k个,这个推一下就好了~
          if(pos < id)dp[j] = query(pos,id-1,1,n,1);
          else dp[j] = max(query(pos,n,1,n,1),query(1,id-1,1,n,1)); 
        }
        int j;
        for(j = i;j <= top;j++){
          if(arr[i].x != arr[j].x)break;
          if(dp[j].first == 0 && arr[j].id > k + 1)continue;//第一个人特判
          dp[j].first++;//以j为结尾的最长上升子序列加1
          int pos = arr[j].id;
          update(pos,pi(dp[j].first,j),1,n,1);//更新最优值
        }
        i = j;
      }
      int ans = 0,rt = 0;
      for(int i = 1;i <= top;i++){
        if(dp[i].first > ans){
          ans = dp[i].first;
          rt = i;
        }
      }
      if(rt == 0)cout << 0 << endl;
      else dfs(rt,0);
      return 0;
    }
    /*
    3 0
    3 1 2 3
    3 1 2 1
    4 1 2 3 2
    */
    View Code
  • 相关阅读:
    Ubuntu之修改用户名和主机名
    HM中CU,TU的划分
    BZOJ 3237([Ahoi2013]连通图-cdq图重构-连通性缩点)
    Introducing Regular Expressions 学习笔记
    kubuntu添加windows字体
    WISE安装程序增加注册控制
    Linux内核中常见内存分配函数(一)
    Linux内核中常见内存分配函数(二)
    Swift现实
    Android 5.0(L) ToolBar(替代ActionBar) 现实(四)
  • 原文地址:https://www.cnblogs.com/cherish-lin/p/11991879.html
Copyright © 2011-2022 走看看