【纪中受难记】——C2Day3:坠入深渊

20/0/0/0

无话可说。


Description

平平带着韵韵来到了游乐园,看到了n辆漂亮的遥控车,每辆车上都有一个唯一的名字name[i]。韵韵早就迫不及待地想玩名字是s的遥控车。可是韵韵毕竟还小,她想象的名字可能是一辆车名字的前缀(也就是说能确定一个i,使s是name[i]的前缀),这时她就能玩第i辆车;或者是一个无中生有的名字,即s不是任何一辆车名字的前缀,这时候她什么也不能玩。
你需要完成下面的任务:
1.韵韵想了m个她想要的名字,请告诉她能玩多少次。
2.由于管理员粗心的操作,导致每辆车的摆放位置都可能出现微小的差错,原来第i辆车现在的位置可能是i-1、i、i+1中的任意一个(第1辆车的位置不可能是0,第n辆车的位置不可能是n+1)。请你计算出共有多少种可能的排列。
注:数据保证当s是name[i]的前缀时,i是唯一确定的。一辆车可以玩多次。
 

Input

第一行是2个正整数n、m。
接下来n行,每行1个字符串name[i],表示第i辆车的名字。
接下来m行,每行1个字符串s,表示韵韵想要的名字。

Output

第一行输出韵韵能玩的次数。
第二行输出共有多少种可能的排列。
 

Sample Input

4 4
Abcd
DeF
AAa
aBccc
Ab
AA
AbC
aBcc

Sample Output

3
5
 

Data Constraint

 
 

Hint

【数据规模和约定】
对于题目涉及到的字符串严格区分大小写,且长度小于255。
对于20%的数据 n≤10,m≤10;
对于40%的数据 n≤1000,m≤1000;
对于100%的数据 n≤10000,m≤10000。

企图使用trie+暴力匹配,炸了。

正解:直接对字符串排序,二分查找。

下面那个题就是求斐波那契数列,要用高精。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1e4+10;
 4 int n,m,ans;
 5 string s[N];
 6 string c;
 7 struct bigint{
 8     char num[100000];
 9     int len;
10     bigint operator =(const bigint &t){
11         strcpy(num,t.num);
12         len=t.len;
13     }//也许这个没啥卵用……
14     bigint operator +(const bigint &t){
15         bigint tmp;
16         tmp.len=0;
17         for(int i=0,g=0;g||i<len||i<t.len;i++){
18             int now=g;
19             if(i<len) now+=num[i]-'0';
20             if(i<t.len) now+=t.num[i]-'0';
21             tmp.num[tmp.len++]=now%10+'0';
22             g=now/10;
23         }
24         return tmp;
25     }
26 }fib[4];
27 int main(){
28     scanf("%d%d",&n,&m);
29     for(int i=1;i<=n;i++) cin>>s[i];
30     sort(s+1,s+n+1);
31     for(int i=1;i<=m;i++){
32         cin>>c;
33         int pos=lower_bound(s+1,s+n+1,c)-s;
34         bool flag=1;
35         for(int j=0;j<c.size();j++){
36             if(c[j]!=s[pos][j]){
37                 flag=0;break;
38             }
39         }
40         ans+=flag;
41     }
42     printf("%d
",ans);
43     fib[0]=(bigint){"1",1};
44     fib[1]=(bigint){"1",1};
45     for(int i=2;i<=n;i++){
46         fib[i%3]=fib[(i-1)%3]+fib[(i-2)%3];
47     }
48     for(int i=fib[n%3].len-1;i>=0;i--){
49         cout<<fib[n%3].num[i];
50     }
51     return 0;
52 }

Description

遥控车是在是太漂亮了,韵韵的好朋友都想来参观,所以游乐园决定举办m次车展。车库里共有n辆车,从左到右依次编号为1,2,…,n,每辆车都有一个展台。刚开始每个展台都有一个唯一的高度h[i]。主管已经列好一张单子:
L1 R1
L2 R2

Lm Rm
单子上的(Li,Ri)表示第i次车展将要展出编号从Li到Ri的车。
为了更加美观,展览时需要调整展台的高度,使参展所有展台的高度相等。展台的高度增加或减少1都需花费1秒时间。由于管理员只有一个人,所以只好对每个展台依次操作。每次展览结束后,展台高度自动恢复到初始高度。
请告诉管理员为了举办所有展览,他最少需要花多少时间将展台调整好。
 

Input

第一行为两个正整数n、m。
第二行共n个非负整数,表示第i辆车展台的高度h[i]。
接下来m行每行2个整数Li、Ri(Li≤Ri)。

Output

一个正整数,调整展台总用时的最小值。
 

Sample Input

6 4
4 1 2 13 0 9
1 5
2 6
3 4
2 2

Sample Output

48
 

Data Constraint

 
 

Hint

【数据规模和约定】
对于50%的数据 n≤500,m≤1000;
对于80%的数据 n≤1000,m≤100000;
对于100%的数据n≤1000,m≤200000;
答案小于2^64。

简单来说就是求区间中位数。

用一个大根堆和一个小根堆搞一下即可。

还是讲一下吧:

就是中位数可以看做从小到大排序好的序列拆成两半中间的那个数字,可以类似的模拟这个过程,前半部分是从小到大的一个大根堆,后半部分是一个从大到小的小根堆,堆顶是最接近中位数的数字。

也可以用主席树(忘了咋写,不写了)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 ll read(){
 5     ll x=0,f=1;
 6     char c=getchar();
 7     while(!isdigit(c)){
 8         if(c=='-') f=-1;
 9         c=getchar();
10     }
11     while(isdigit(c)){
12         x=(x<<1)+(x<<3)+(c^48);
13         c=getchar();
14     }
15     return x*f;
16 }
17 const ll N=1010;
18 ll n,m;
19 ll ans,bsum,ssum; 
20 ll a[N];
21 ll mid[N][N];
22 priority_queue<int,vector<int>,less<int> > big;
23 priority_queue<int,vector<int>,greater<int> > small;
24 int main(){
25     n=read();m=read();
26     for(int i=1;i<=n;i++) a[i]=read();
27     for(int i=1;i<=n;i++){
28         while(!big.empty()) big.pop();
29         while(!small.empty()) small.pop();
30         bsum=ssum=0;
31         for(int j=i;j<=n;j++){
32             if(big.size()==small.size()){
33                 big.push(a[j]);
34                 bsum+=a[j];
35             }
36             else{
37                 small.push(a[j]);
38                 ssum+=a[j];
39             }
40             if(big.size()&&small.size()){
41                 int bx=big.top(),sx=small.top();
42                 if(sx<bx){
43                     small.pop();
44                     big.pop();
45                     small.push(bx);
46                     big.push(sx);
47                     ssum=ssum-sx+bx;
48                     bsum=bsum-bx+sx;
49                 }
50             }
51             mid[i][j]=bsum-big.top()*big.size()+big.top()*small.size()-ssum;
52         }
53     }
54     for(int i=1,x,y;i<=m;i++){
55         x=read();y=read();
56         ans-=mid[x][y];
57     }
58     printf("%lld",ans);
59     return 0;
60 }

不要问我为什么用负数更新答案。


Description

车展结束后,游乐园决定举办一次盛大的山道拉力赛,平平和韵韵自然也要来参加大赛。
赛场上共有n个连通的计时点,n-1条赛道(构成了一棵树)。每个计时点的高度都不相同(父结点的高度必然大于子结点),相邻计时点间由赛道相连。由于马力不够,所以韵韵的遥控车只能从高处驶向低处。而且韵韵的车跑完每条赛道都需花费一定的时间。
举办方共拟举办m个赛段的比赛,每次从第u个计时点到第v个计时点,当然其中有不少比赛韵韵的遥控车是不能参加的(因为要上坡)。平平想知道他能参加多少个赛段的比赛,并且想知道他完成这些赛段的总用时。
 

Input

第一行两个整数n,m。
接下来n-1行每行3个整数a、b、t。
表示韵韵的遥控车可以花t秒从第a个计时点到第b个计时点。
接下来m行每行2个整数u、v,意义如描述所示。

Output

第一行输出一个正整数,表示能参加的赛段数。
第二行输出一个正整数,表示总用时。
 

Sample Input

6 2
1 2 1
2 4 1
2 5 1
5 6 1
1 3 1
2 6
4 5

Sample Output

1
2
 

Data Constraint

 
 

Hint

【数据规模和约定】
第一个计时点的高度是最高的;
u≠v;
对于50%的数据 n≤1000 m≤1000;
对于100%的数据 n≤10000 m≤100000;
答案小于2^64。

倍增。

注意判一下深度啊。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 inline int read(){
 4     int x=0,f=1;
 5     char c=getchar();
 6     while(!isdigit(c)){
 7         if(c=='-') f=-1;
 8         c=getchar();
 9     }
10     while(isdigit(c)){
11         x=(x<<1)+(x<<3)+(c^48);
12         c=getchar();
13     }
14     return x*f;
15 }
16 const int N=1e4+10;
17 const int M=1e5+10;
18 int n,m,cnt;
19 long long ans1,ans2;
20 int f[N][25],head[M<<1],dep[N],det[N];
21 struct edge{
22     int to,next,w;
23 }e[M<<1];
24 void addedge(int from,int to,int w){
25     e[++cnt]=(edge){to,head[from],w};
26     head[from]=cnt;
27 }
28 void dfs(int u,int fa){
29     f[u][0]=fa;
30     det[u]=det[fa]+1;
31     for(int i=head[u];i;i=e[i].next){
32         int v=e[i].to,w=e[i].w;
33         if(v==fa) continue;
34         dep[v]=dep[u]+w;
35         dfs(v,u);
36     }
37 }
38 int main(){
39 //    freopen("data2.in","r",stdin);
40     n=read();m=read();
41     for(int i=1,x,y,z;i<n;i++){
42         x=read();y=read();z=read();
43         addedge(x,y,z);
44         addedge(y,x,z);
45     }
46     dfs(1,0);
47     for(int j=1;j<=20;j++){
48         for(int i=1;i<=n;i++){
49             f[i][j]=f[f[i][j-1]][j-1];
50         }
51     }
52     for(register int i=1,x_,y_;i<=m;i++){
53         x_=read();y_=read();
54         int x=x_,y=y_;
55         if(det[x]>det[y]) continue;
56         int j=20;
57         for(int j=20;j>=0;j--){
58             if(det[f[y][j]]>=det[x]) y=f[y][j];
59         }
60         if(x==y){
61             ans1++;
62             ans2+=dep[y_]-dep[x_];
63         }
64     }
65     printf("%lld
%lld",ans1,ans2);
66     return 0;
67 }

Description

游乐园决定在一个n×m的广场上举办一次颁奖晚会,总管要你帮忙搭建一个舞台。
现在给你广场的布置图(规定地图的上方为正北),有些位置需要布置为观众席(记为1),另一些是空地(记为0)。舞台只能在空地上搭建。
为了使晚会更加吸引人,平平觉得舞台应该是朝北的h—金字塔形。h—金字塔形舞台是由h个矩形舞台相接而成的,其中后方的矩形舞台的两端必须超出在其前面的矩形舞台,且最小矩形面对的朝向为舞台的方向。下面给出几个实例:

舞台的面积应该尽量大,输出面积最大的朝北h—金字塔形舞台的面积。
 

Input

第一行3个整数 n、m、h。
接下来n行,每行m个0或1,中间用一个空格隔开。

Output

一个整数,表示最大的朝北的h—金字塔形舞台的面积。
如果没有符合题意的h—金字塔形舞台输出0。
 

Sample Input

4 6 2
0 0 1 0 0 1
0 0 0 0 0 0
0 0 1 0 0 0
0 1 1 0 0 0

Sample Output

10
 

Data Constraint

 
 

Hint

样例对应的最优方案如下图:

×表示观众席
【数据规模和约定】
对于10%的数据 h=1;
对于40%的数据 h≤5;
对于100%的数据 h≤20;
对于100%的数据 n、m≤100。

dp题。

f[i][j][l][r]表示第i行,此时放了j个矩形,在区间[l,r]放矩形的最大面积。

g[i][j][l][r]表示第i行,此时放了j个矩形,在区间(l,r)放矩形的最大面积。

转移:

g[i][j][l][r]=max(g[i][j][l+1][r],g[i][j][l][r-1],f[i][j][l+1][r-1])

f[i][j][l][r]=max(f[i-1][j][l][r],g[i-1][j-1][l][r])+r-l+1或0(看这一行l到r是否都为0).

滚动一下即可AC。

注意枚举顺序。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int read(){
 4     int x=0,f=1;
 5     char c=getchar();
 6     while(!isdigit(c)){
 7         if(c=='-') f=-1;
 8         c=getchar();
 9     }
10     while(isdigit(c)){
11         x=(x<<1)+(x<<3)+(c^48);
12         c=getchar();
13     }
14     return x*f;
15 }
16 const int N=110;
17 int n,m,h,ans;
18 bool a[N][N];
19 int s[N][N];
20 int f[2][25][N][N],g[2][25][N][N];
21 int main(){
22     n=read();m=read();h=read();
23     for(int i=1;i<=n;i++){
24         for(int j=1;j<=m;j++){
25             a[i][j]=read();
26             s[i][j]=s[i][j-1]+a[i][j];
27         }
28     }
29     for(int i=1;i<=n;i++){
30         int p=i%2;
31         for(int j=1;j<=h;j++){
32             for(int l=m;l>=1;l--){
33                 for(int r=l;r<=m;r++){
34                     if(r-l+1>=3) g[p][j][l][r]=max(g[p][j][l+1][r],max(g[p][j][l][r-1],f[p][j][l+1][r-1]));
35                     
36                     if((s[i][r]-s[i][l-1]==0)&&(j==1||g[p^1][j-1][l][r]>0)){
37                         
38                         f[p][j][l][r]=max(f[p^1][j][l][r],g[p^1][j-1][l][r])+r-l+1;
39                         if(j==h) ans=max(ans,f[p][j][l][r]);
40                         
41                     }
42                     else f[p][j][l][r]=0;
43 
44 //                    if(i==1&&j==1&&l==5&&r==5){
45 //                        cout<<g[p][j][l][r]<<endl;
46 //                    }
47                 }
48             }
49         }
50     }
51     printf("%d",ans);
52     return 0;
53 }
——抓住了时间,却不会利用的人,终究也逃不过失败的命运。
原文地址:https://www.cnblogs.com/Nelson992770019/p/11627544.html