CF750E 线段树+矩阵乘矩阵加

题目描述

A string tt is called nice if a string "2017" occurs in tt as a subsequence but a string "2016" doesn't occur in tt as a subsequence. For example, strings "203434107" and "9220617" are nice, while strings "20016", "1234" and "20167" aren't nice.

The ugliness of a string is the minimum possible number of characters to remove, in order to obtain a nice string. If it's impossible to make a string nice by removing characters, its ugliness is -11 .

Limak has a string ss of length nn , with characters indexed 11 through nn . He asks you qq queries. In the ii-th query you should compute and print the ugliness of a substring (continuous subsequence) of ssstarting at the index a_{i}ai and ending at the index b_{i}bi (inclusive).

输入输出格式

输入格式:

The first line of the input contains two integers nn and qq ( 4<=n<=2000004<=n<=200000 , 1<=q<=2000001<=q<=200000 ) — the length of the string ss and the number of queries respectively.

The second line contains a string ss of length nn . Every character is one of digits '0'–'9'.

The ii -th of next qq lines contains two integers a_{i}ai and b_{i}bi ( 1<=a_{i}<=b_{i}<=n1<=ai<=bi<=n ), describing a substring in the ii -th query.

 

输出格式:

 

For each query print the ugliness of the given substring.

输入输出样例

输入样例#1:
8 3
20166766
1 8
1 7
2 8
输出样例#1:
4
3
-1
输入样例#2:
15 5
012016662091670
3 4
1 14
4 15
1 13
10 15
输出样例#2:
-1
2
1
-1
-1
输入样例#3:
4 2
1234
2 4
1 2
输出样例#3:
-1
-1

说明

In the first sample:

  • In the first query, ugliness(ugliness( "20166766" )=4)=4 because all four sixes must be removed.
  • In the second query, ugliness(ugliness( "2016676" )=3)=3 because all three sixes must be removed.
  • In the third query, ugliness(ugliness( "0166766" )=-1)=1 because it's impossible to remove some digits to get a nice string.

In the second sample:

  • In the second query, ugliness(ugliness( "01201666209167" )=2)=2 . It's optimal to remove the first digit '2' and the last digit '6', what gives a string "010166620917", which is nice.
  • In the third query, ugliness(ugliness( "016662091670" )=1)=1 . It's optimal to remove the last digit '6', what gives a nice string "01666209170".

-------------------------------------------------------------------

这是一个大坑

先把代码丢在这里,改天详细写个题解 233333

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define N 200100
 7 #define INF 1e9
 8 #define lc (p<<1)
 9 #define rc (p<<1|1)
10 using namespace std;
11 int n,m;
12 char s[N];
13 struct node
14 {
15     int a[5][5];
16     node(){
17         for(int i=0;i<5;i++)
18             for(int j=0;j<5;j++)
19                 a[i][j]=INF;
20     }
21 }T[N<<2];
22 char ch[]={'2','0','1','7','6'};
23 int find (char x)//返回数字本身的愚蠢办法
24 {
25     for(int i=0;i<5;i++)
26         if(x==ch[i]) return i;
27     return -1;
28 }
29 node pushup(node &a,node &b){
30     node res;
31     for(int i=0;i<5;i++)
32         for(int j=i;j<5;j++)
33             for(int k=i;k<=j;k++)
34                 res.a[i][j]=min(res.a[i][j],a.a[i][k]+b.a[k][j]);
35     return res;
36 }
37 void build(int p,int l,int r)
38 {
39     if(l==r)
40     {
41         int f=find(s[l]);
42         for(int i=0;i<5;i++)
43             T[p].a[i][i]=0;//初始化——隔壁有更好的方法
44         
45         //以下为转移方程初始化
46         if(f!=-1&&f<4)//l的值为2 0 1 7
47         {
48             T[p].a[f][f+1]=0;
49             T[p].a[f][f]=1;
50         }
51         else if(f==4)//l为6
52             T[p].a[3][3]=T[p].a[4][4]=1;
53         return;
54     }
55     int mid=(l+r)>>1;
56     build(lc,l,mid);
57     build(rc,mid+1,r);
58     T[p]=pushup(T[lc],T[rc]);
59 }
60 node query(int p,int l,int r,int ql,int qr)
61 {
62     if(ql==l&&qr==r)
63         return T[p];
64     int mid=(l+r)>>1;
65     if(qr<=mid) return query(lc,l,mid,ql,qr);
66     if(ql>mid) return query(rc,mid+1,r,ql,qr);
67     else
68     {
69         node tmpl=query(lc,l,mid,ql,mid);
70         node tmpr=query(rc,mid+1,r,mid+1,qr);
71         return pushup(tmpl,tmpr);
72     }
73 }
74 int main()
75 {
76     scanf("%d%d",&n,&m);
77     scanf("%s",s+1);
78     build(1,1,n);
79     while(m--)
80     {
81         int l,r;
82         scanf("%d%d",&l,&r);
83         int ans=query(1,1,n,l,r).a[0][4];
84         if(ans==INF) printf("-1\n");
85         else printf("%d\n",ans);
86     }
87     return 0;
88 }

 

posted @ 2018-09-10 21:41  flowphyl  阅读(314)  评论(0编辑  收藏  举报