zoukankan      html  css  js  c++  java
  • Codeforces GYM 100114 D. Selection 线段树维护DP

    D. Selection

    Time Limit: 1 Sec  

    Memory Limit: 256 MB

    题目连接

    http://codeforces.com/gym/100114

    Description

    When selecting files in an application dialog, Vasya noted that he can get the same selection in different ways. A simple mouse click selects a single file (the existing selection is discarded). A shift-click is used to select a range of files from the file clicked last time to the current file (the existing selection is discarded). Finally, a control-click is used to invert the selection state of a single file. Consider a sequence of actions. First we select file #5 simply by clicking it. Then, shift-clicking file #10 we get the following selection: #5, #6, #7, #8, #9, #10. If after that we control-click files #7 and #3 then we will have files #3, #5, #6, #8, #9, and #10 selected. Shift-clicking file #1 we select files #1, #2, and #3 (last time we clicked file #3, and the previous selection is gone). Vasya is wondering, what the minimum number of clicks will be, to make a certain selection from the list of files. Write a program to determine the optimal way of making the required selection. If there are several minimal solutions, any of them is considered correct. Example. Suppose we are to select files #2, #5, #6, #8, #9 from a list of 10 files. A possible optimal solution will include the following clicks: 5, Shift+9, Ctrl+2, Ctrl+7.

    Input

    The first line contains an integer n, the number of files in the list. The following line contains n characters defining the required selection. If i-th file is to be selected then there is an asterisk (“*”) in position i, and a dot (“.”) otherwise.

    Output

    The first line of the output file must contain a single integer k – the minimum number of clicks necessary to make the given selection. The following k lines must define the way to make such a selection. Each line should contain the number of file to be clicked on the corresponding step, and a prefix “Ctrl+” or “Shift+” (without quotation marks) where necessary.

    Sample Input

    10 .*..**.**.

    Sample Output

    4 5 Shift+9 Ctrl+2 Ctrl+7

    HINT

    1 ≤ n ≤ 105 .

    题意

    有3种操作

    1.光标移动到X

    2.shift X,直接选择从光标到X的位置

    3.选择X,如果X已经被选中,那就取消X的选中状态

    问你最少多少步,可以选择所有的*

    并且把步骤输出

    题解:

    注意,只能shift 1次,所以直接扫一遍就好了

    跑一遍线段树维护的DP,表示到这儿,所需要的最小代价是多少

    代码:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    #include <stack>
    #include <map>
    #include <set>
    #include <queue>
    #include <iomanip>
    #include <string>
    #include <ctime>
    #include <list>
    #include <bitset>
    typedef unsigned char byte;
    #define pb push_back
    #define input_fast std::ios::sync_with_stdio(false);std::cin.tie(0)
    #define local freopen("in.txt","r",stdin)
    #define pi acos(-1)
    
    using namespace std;
    const int maxn = 1e5 + 500;
    char str[maxn];
    int length , sum[maxn], dp[maxn];
    vector<int>Q,Q2;
    
    struct operation
    {
        int x;
        int type;
    };
    
    operation nxt[maxn];
    
    struct QueryData
    {
        int minv , minpos;
        QueryData(int minv , int minpos)
        {
            this->minv = minv , this->minpos = minpos;
        }
    };
    
    typedef int SgTreeDataType;
    struct treenode
    {
      int L , R  ;
      SgTreeDataType minv , minpos;
      void updata(SgTreeDataType v)
      {
            minv = v;
      }
    };
    
    
    treenode tree[maxn * 4];
    
    
    inline void push_up(int o)
    {
        if(tree[o*2].minv > tree[o*2+1].minv)
        {
            tree[o].minv = tree[o*2+1].minv;
            tree[o].minpos = tree[o*2+1].minpos;
        }
        else
        {
            tree[o].minv = tree[o*2].minv;
            tree[o].minpos = tree[o*2].minpos;
        }
    }
    
    inline void build_tree(int L , int R , int o)
    {
        tree[o].L = L , tree[o].R = R,tree[o].minv = 1<<29 , tree[o].minpos = 0;
        if(L == R) tree[o].minpos = L;
        if (R > L)
        {
            int mid = (L+R) >> 1;
            build_tree(L,mid,o*2);
            build_tree(mid+1,R,o*2+1);
        }
    }
    
    inline void updata(int QL,int QR,SgTreeDataType v,int o)
    {
        int L = tree[o].L , R = tree[o].R;
        if (QL <= L && R <= QR) tree[o].updata(v);
        else
        {
            int mid = (L+R)>>1;
            if (QL <= mid) updata(QL,QR,v,o*2);
            if (QR >  mid) updata(QL,QR,v,o*2+1);
            push_up(o); 
        }
    }
    
    inline QueryData query(int QL,int QR,int o)
    {
        int L = tree[o].L , R = tree[o].R;
        if (QL <= L && R <= QR) return QueryData(tree[o].minv,tree[o].minpos);
        else
        {
            int mid = (L+R)>>1;
            if (QL <= mid && QR > mid)
            {
                QueryData a = query(QL,QR,2*o);
                QueryData b = query(QL,QR,2*o+1);
                if(a.minv < b.minv) return a;
                else return b;
            }
            else if (QL <= mid) return query(QL,QR,2*o);
            else return query(QL,QR,2*o+1);
        }
    }
    
    void initiation()
    {
        memset( dp , 0 , sizeof(dp));
        scanf("%d%s",&length,str+1);sum[0] = 0;
        for(int i = 1 ; i <= length ; ++ i)
        {
            sum[i] = sum[i-1];
            if(str[i] == '*')
            {
                Q.push_back(i);
            }
            else
            {
                sum[i] ++ ;
                Q2.push_back(i);
            }
        }
    }
    
    
    void solve()
    {
        int sz = Q.size();
        int ansL = Q[0],ansR = Q[0],ans=sz;
        build_tree( 0 , sz - 1 , 1 );
        for(int i = 0 ; i < sz ; ++ i) updata( i , i , sum[Q[i]] - i , 1);
        for(int i = 0 ; i < sz - 1; ++ i)
        {
            QueryData y = query( i + 1 , sz  - 1, 1);
            int newans = i + 1 + sz + y.minv - sum[Q[i]];
            if(newans < ans)
            {
                ans = newans;
                ansL = i;
                ansR = y.minpos;
            }
        }
        printf("%d
    ",ans);
        if(ansL != ansR)
        {
            printf("%d
    ",Q[ansL]);
            printf("Shift+%d
    ",Q[ansR]);
            for(int i = 0 ; i < sz ; ++ i) if(i < ansL || i > ansR) printf("Ctrl+%d
    ",Q[i]);
            for(int i = 0 ; i < Q2.size() ; ++ i) if( Q2[i] < Q[ansR] && Q2[i] > Q[ansL]) printf("Ctrl+%d
    ",Q2[i]);
        }
        else
        {
            printf("%d
    ",Q[0]);
            for(int i = 1 ; i < sz ; ++ i) printf("Ctrl+%d
    ",Q[i]);
        }
    }
    
    
    
    int main(int argc,char *argv[])
    {
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        initiation();
        if(Q.size() == 0) printf("0
    ");
        else if(Q.size() == 1) printf("1
    %d
    ",Q[0]);
        else if(Q.size() == 2) printf("2
    %d
    Ctrl+%d
    ",Q[0],Q[1]);
        else solve();
        return 0;
    }
  • 相关阅读:
    w3wp.exe占用CPU100%的解决办法
    Visual Studio 2005 查找和替换窗口 显示不了
    IIS:w3wp.exe进程占用cpu和内存过多的处理办法
    C# form ComboBox
    从尾到头打印链表,不允许逆置原链表
    [置顶] ATL窗口thunk机制的剖析与实现
    flex自定义用ArrayCollection做数据源的带checkbox的tree(功能强大的完美版^_^)
    oracle的PremaredStatement.executeBatch为什么返回2
    窗体Controls的OfType<>方法的使用
    HDU 1421 动态规划(DP) 搬寝室
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4780559.html
Copyright © 2011-2022 走看看