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

2020 2.9

时间:2020-02-13 22:44:23      阅读:51      评论:0      收藏:0      [点我收藏+]

标签:return   增加   查找   lse   def   处理   pos   none   选择   

t1#1433. 【Mogic WXH Round #9】敲响WXH的钟

Description

很久很久之前,人们就相信着智慧之神WXH的存在。他们相信WXH的化身会引导他们走向正确的未来。为此诞生了一个宗教组织叫22眼佬神教(因为人们相信WXH的神体应当有22只眼)

有一天晚上,著名佬学家mcfx做了一个梦。在梦里,mcfx发现自己躺在绿色的草原上,他眼前出现了一团金光。

...请好好对待我的分身...他将引导你们...

mcfx盯着那团金光,金光似乎也在看他。mcfx发现自己似乎正陷入金光之中,周围隐隐约约地显现出许许多多的文字和一个个变化多端的结构。接着,mcfx手上突然多了3道题。这是什么意思呢?mcfx刚想说话,周围的一切便陷入了混沌中。迷惑的mcfx翻了个身,又睡着了。然而,他不知道的是,第二天是2001年9月10日,在这一天有一个人诞生了,未来将由他来指引,他将被写进歌里世世代代传唱下去...

醒来后,mcfx只想起了第1道题。这道题是这样的:

给定一个包含前K个大写字母的字符串,定义字符串的值为

对相邻字符产生代价之和c[i][j]

mcfx可以选择在这个字符串中去掉一些种类的字母,去掉的代价为t[i]

产生的字符串代价为去掉的代价+该字符串本身代价mcfx发现t会升高次,他想实时知道有多少种能产生的字符串代价

Input

第一行输入正整数

接下来一个长为

的字符串

接下来

个正整数表示

接下来一个

的矩阵

(不一定对称)表示相邻字符产生的代价

接下来输入一个正整数

接下来输入

组询问表示

Output

第一行输出询问前的答案

接下来输出

行答案

Sample Input

20 10 687688697
CIICAIHHCDGCABDEHIDI
3077538 187154934 7962438 32751 150915363 8369048 237235 1211323 118266 130804 4732363 60914208 3940339 914881 229440008 65912272 3079365 1399630 32573 13530910 
98278 14496734 194557 32725 147346 270321 91582031 6112899 786423 228914 
31227677 57342 473460 117439485 717620 188368 2254930 56783 122750 121847 
65211 223830300 181381333 490347 128794 1007356 340354058 117448 81918 114682 
374647 50067167 738849507 34953229 48508 130523 89069 90104 291824 1899224 
995606 28064599 6389618 13827585 18559 58812027 62455151 32298 65398 65025987 
932360575 678623341 379323390 40908 174451 45017 60489447 44858 4386617 28668 
524248 481941303 13299664 5298639 458619 218732 4615534 14524 131623295 1013183 
73324271 14052731 94183 55070 269548161 374266 177142 18284070 302657933 192255 
125945 14904784 61418 391062 257533 23623544 39540794 5681968 31869874 15190899 
10
5 145325
8 7404003
8 64650466
1 2948826
3 916473
4 716430863
5 122864
6 25819674
6 81343
5 350308901

Sample Output

82
82
82
80
80
80
34
34
34
34
23

题解
发现所有的字符在删除一些字符后后头可以巴起的字符最多就只有K种,所以装压求出所有删除情况的字符串初始代价。
然后二分查找出t增加了几次后这一种情况不能用了,差分处理每一种情况啥子时候不能用了。
现在问题就是囊个求每种状态初始字符串的值。
使用高维前缀和。
如果在删去状态now后i和j相邻了,则f[now]+=c[][],f[now|1<<i]-=c[dui[i]][dui[j]],f[now|1<<j]-=c[][],f[now|1<<i|1<<j]+=c[][]
然后真正的f[i]就是i的所有子集之和。
代码如下:
技术图片
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int n,k,T,t[N],st[N],top,ma[22][22],f[1<<20],b[N],pos[N],sum[N][22],ans[N];
char c[N];
inline int read()
{
    char c=getchar();
    int x=0,f=1;
    while(!isdigit(c)) {if(c==-) f=-1;c=getchar();}
    while(isdigit(c)) {x=(x<<3)+(x<<1)+c-0;c=getchar();}
    return x*f;
}
inline bool cmp(int x,int y)
{
    return pos[x]>pos[y];
}
signed main()
{
    n=read();k=read();T=read();
    scanf("%s",c+1);
    for(int i=1;i<=k;i++) t[i]=read();
    for(int i=1;i<=k;i++) for(int j=1;j<=k;j++) ma[i][j]=read();
    for(int i=1;i<=k;i++) b[i]=i;
    for(int i=1;i<=n;i++)
    {
        int now=c[i]-A+1;
        sort(b+1,b+k+1,cmp);
        int nows=0;
        for(int j=1;j<=k;j++)
        {
            if(!pos[b[j]]) break;
            f[nows]+=ma[b[j]][now];
            f[nows|(1<<b[j]-1)]-=ma[b[j]][now];
            f[nows|(1<<now-1)]-=ma[b[j]][now];
            f[nows|(1<<now-1)|(1<<b[j]-1)]+=ma[b[j]][now];
            nows|=(1<<b[j]-1);
        }
        pos[now]=i;
    }
    for(int i=1;i<(1<<k);i<<=1)
        for(int j=0;j<(1<<k);j++)if(j&i)
            f[j]+=f[j^i];
//    for(int i=0;i<1<<k;i++)
//        for(int j=0;j<k;j++)
//            if(i&(1<<j))
//                f[i]+=f[i^(1<<j)];
    for(int i=0;i<1<<k;i++)
        for(int j=1;j<=k;j++)
            if(i&(1<<j-1))
                f[i]+=t[j];
    int q=read();
    for(int i=1,x,y;i<=q;i++)
    {
        x=read();y=read();
        for(int j=1;j<=k;j++) sum[i][j]=sum[i-1][j];
        sum[i][x]+=y;
    }
    for(int i=0;i<(1<<k);i++)
    {
        int top=0;
        for(int j=1;j<=k;j++)
            if(i&(1<<j-1))
            {
                if(!pos[j])
                {
                    top=-1;
                    break;
                }
                st[++top]=j;
            }
        if(top==-1||f[i]>T) continue;
    
        int l=1,r=q,daan=0;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            int now=f[i];
            for(int j=1;j<=top;j++)
                now+=sum[mid][st[j]];
            if(now<=T) daan=mid,l=mid+1;
            else r=mid-1;
        }
        ans[daan+1]--;ans[0]++;
    }
    cout<<ans[0]<<"\n";
    for(int i=1;i<=q;i++) ans[i]+=ans[i-1],cout<<ans[i]<<"\n";
    return 0;
}
//20 10 687688697
//CIICAIHHCDGCABDEHIDI
//3077538 187154934 7962438 32751 150915363 8369048 237235 1211323 118266 130804 4732363 60914208
//3940339 914881 229440008 65912272 3079365 1399630 32573 13530910
//98278 14496734 194557 32725 147346 270321 91582031 6112899 786423 228914
//31227677 57342 473460 117439485 717620 188368 2254930 56783 122750 121847
//65211 223830300 181381333 490347 128794 1007356 340354058 117448 81918 114682
//374647 50067167 738849507 34953229 48508 130523 89069 90104 291824 1899224
//995606 28064599 6389618 13827585 18559 58812027 62455151 32298 65398 65025987
//932360575 678623341 379323390 40908 174451 45017 60489447 44858 4386617 28668
//524248 481941303 13299664 5298639 458619 218732 4615534 14524 131623295 1013183
//73324271 14052731 94183 55070 269548161 374266 177142 18284070 302657933 192255
//125945 14904784 61418 391062 257533 23623544 39540794 5681968 31869874 15190899
//10
//5 145325
//8 7404003
//8 64650466
//1 2948826
//3 916473
//4 716430863
//5 122864
//6 25819674
//6 81343
//5 350308901
View Code

 

 

2020 2.9

标签:return   增加   查找   lse   def   处理   pos   none   选择   

原文地址:https://www.cnblogs.com/betablewaloot/p/12305514.html

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