1. 程式人生 > >牛客練習賽16

牛客練習賽16

mes 編號 其它 ioe true def %s long long #define

A 字典序最大的子序列 > 25960019

一開始潛意識看成了循環,最長子串……

找每個字母最晚出現的位置,那麽比它小的字符必須出現在 在它之後的位置

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <set>
 6 #include <map>
 7 #include <list>
 8 #include <stack>
 9 #include <queue>
10
#include <vector> 11 #include <algorithm> 12 #include <iostream> 13 using namespace std; 14 #define ll long long 15 const long maxn=1e6+50; 16 const ll mod=1e9+7; 17 18 char s[maxn]; 19 long a[27],b[27]; 20 21 int main() 22 { 23 long len,i; 24 scanf("%s",s); 25 len=strlen(s);
26 for (i=0;i<=26;i++) 27 a[i]=-1; 28 for (i=0;i<len;i++) 29 a[s[i]-97]=i; 30 b[26]=-1; 31 for (i=25;i>=0;i--) 32 b[i]=max(b[i+1],a[i]); 33 for (i=0;i<len;i++) 34 if (b[s[i]-97+1]<i) 35 printf("%c",s[i]); 36 return 0; 37 }
38 /* 39 dsfasfaowjfwoeijwalgkargkwefaweioewajfwo 40 */

B 漂亮的樹 > 25974107

分奇數和偶數,最後的數之間的差值是固定的,如1,2,3,2,1 ; 1,2,2,1

原來的數減去最終的數(以a[1]=x為基準),求出現次數最多的數。

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <set>
 6 #include <map>
 7 #include <list>
 8 #include <stack>
 9 #include <queue>
10 #include <vector>
11 #include <algorithm>
12 #include <iostream>
13 using namespace std;
14 #define ll long long
15 const long maxn=1e5+5;
16 const ll mod=1e9+7;
17  
18 long a[maxn],b[maxn*2];
19  
20 int main()
21 {
22     long n,r,i,x;
23     scanf("%ld",&n);
24     a[1]=0;
25     for (i=1;i<=(long)(1.0*n/2);i++)
26         a[i+1]=a[i]+1;
27     for (i=n/2+1;i<=n;i++)
28         a[i]=a[n+1-i];
29     for (i=0;i<=1e5*2;i++)
30         b[i]=0;
31     for (i=1;i<=n;i++)
32     {
33         scanf("%ld",&x);
34         b[x-a[i]+100000]++;
35     }
36     r=0;
37     for (i=0;i<=1e5*2;i++)
38         r=max(r,b[i]);
39     printf("%ld",n-r);
40     return 0;
41 }
42 /*
43 5
44 1 2 3 2 1
45 4
46 1 2 2 1
47 */

C 任意點 > 25961653

若兩點的橫坐標或縱坐標相等,則它們在同一組,求組數

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <set>
 6 #include <map>
 7 #include <list>
 8 #include <stack>
 9 #include <queue>
10 #include <vector>
11 #include <algorithm>
12 #include <iostream>
13 using namespace std;
14 #define ll long long
15 const long maxn=1e3+5;
16 const ll mod=1e9+7;
17  
18 long x[maxn],y[maxn],n;
19 bool vis[maxn];
20  
21 void dfs(long d)
22 {
23     vis[d]=true;
24     long i;
25     for (i=1;i<=n;i++)
26         if ((x[i]==x[d] || y[i]==y[d]) && !vis[i])
27             dfs(i);
28 }
29  
30 int main()
31 {
32     long i,c;
33     scanf("%ld",&n);
34     for (i=1;i<=n;i++)
35         scanf("%ld%ld",&x[i],&y[i]);
36     for (i=1;i<=n;i++)
37         vis[i]=false;
38     c=0;
39     for (i=1;i<=n;i++)
40         if (!vis[i])
41         {
42             c++;
43             dfs(i);
44         }
45     printf("%ld",c-1);
46     return 0;
47 }

D k進制數 > 25967939

額,其實要是樣例沒有把解題思路和易錯點說得這麽清晰,那這道題就是好題了……

紙上做模擬,發現當所有位之和為n,則:

n=0,結果為0,

否則,

m=n%(k-1),

如果m=0,則結果為k-1,

否則結果為m。

對結果為0,k-1和其它 分別求解

結果為0:求0的個數。如0,0,0,1,2,3,0,0,2,0,則f(3)+f(2)+f(1)=3*4/2 + 2*3/2 + 1*2/2.

結果為k-1,減去上述為0的個數。

結果為0~k-1:

x(i)記錄前i個數之和,g(i)記錄所有x(j) [j=1..i]中,余數為(i-b+k-1)%(k-1)的個數,從而之後當x(w)=i,以第w位為結尾的子串中,子串和除以(k-1)等於b的個數為g(i)個。

因為內存限制,所以要進行離散化……

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <set>
 6 #include <map>
 7 #include <list>
 8 #include <stack>
 9 #include <queue>
10 #include <vector>
11 #include <algorithm>
12 #include <iostream>
13 using namespace std;
14 #define ll long long
15 const long maxn=1e5+5;
16 const ll mod=1e9+7;
17 
18 long a[maxn],x[maxn],g[maxn*2];
19 map<long,long>f;
20 set<long>s;
21 
22 int main()
23 {
24     long k,b,n,i,j,num,nn;
25     ll ans=0;
26     scanf("%ld%ld%ld",&k,&b,&n);
27     for (i=1;i<=n;i++)
28         scanf("%ld",&a[i]);
29     if (b==0)
30     {
31         for (i=1;i<=n;i++)
32             if (a[i]==0)
33             {
34                 j=i;
35                 while (i!=n && a[i+1]==0)
36                     i++;
37                 ans=ans+(long long)(i-j+2)*(i-j+1)/2;
38             }
39         printf("%lld",ans);
40         return 0;
41     }
42     else if (b==k-1)
43     {
44         for (i=1;i<=n;i++)
45             if (a[i]==0)
46             {
47                 j=i;
48                 while (i!=n && a[i+1]==0)
49                     i++;
50                 ans=ans-(long long)(i-j+2)*(i-j+1)/2;
51             }
52         b=0;
53     }
54 
55     k--;
56     s.clear();
57     x[0]=0;
58     for (i=1;i<=n;i++)
59     {
60         x[i]=(x[i-1]+a[i])%k;
61         s.insert(x[i]);
62         s.insert((x[i]+b)%k);
63     }
64     s.insert(b);
65     set<long>::iterator z;
66     f.clear();
67     for (z=s.begin(),num=0;z!=s.end();z++,num++)
68         f[*z]=num;
69     for (i=0;i<num;i++)
70         g[i]=0;
71     g[f[b]]=1;
72     for (i=1;i<=n;i++)
73     {
74         ans=ans+(long long)g[f[x[i]]];
75         g[f[(x[i]+b)%k]]++;
76     }
77     printf("%lld",ans);
78     return 0;
79 }
80 /*
81 7 6 10
82 0 3 0 0 5 0 4 0 0 0
83 
84 
85 7 6 5
86 0 0 0 0 0
87 
88 7 6 6
89 0 0 0 0 0 6
90 
91 7 6 8
92 0 0 0 0 2 4 0 0
93 
94 7 6 9
95 0 0 0 0 2 4 0 0 6
96 
97 10 5 2
98 1 2
99 */

E 求值 > 25970027

求從某個數開始,第一次 數的第i位為1的數的編號,最多有20個(2^20=1048576),從而時間復雜度O(20n)。

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <set>
 6 #include <map>
 7 #include <list>
 8 #include <stack>
 9 #include <queue>
10 #include <vector>
11 #include <algorithm>
12 #include <iostream>
13 using namespace std;
14 #define ll long long
15 #define inf 1e9
16 const long maxn=1e5+5;
17 const ll mod=1e9+7;
18  
19 long a[maxn],nex[maxn][30];
20 bool vis[maxn][30],use[1048576+5];
21 long num[30];
22  
23 int main()
24 {
25     long n,b,i,j,k,g;
26     scanf("%ld",&n);
27     for (i=1;i<=n;i++)
28     {
29         scanf("%ld",&a[i]);
30         j=0;
31         b=a[i];
32         while (b)
33         {
34             if (b & 1)
35                 vis[i][j]=1;
36             else
37                 vis[i][j]=0;
38             j++;
39             b>>=1;
40         }
41     }
42     for (j=0;j<20;j++)
43         nex[n+1][j]=inf;
44     for (i=n;i>=1;i--)
45         for (j=0;j<20;j++)
46             if (vis[i][j])
47                 nex[i][j]=i;
48             else
49                 nex[i][j]=nex[i+1][j];
50  
51     for (i=0;i<1048576;i++)
52         use[i]=0;
53     for (i=1;i<=n;i++)
54     {
55         g=0;
56         for (j=0;j<20;j++)
57             if (nex[i][j]!=inf)
58             {
59                 num[g]=nex[i][j];
60                 g++;
61             }
62         sort(num,num+g);
63         k=a[i];
64         use[k]=1;
65         for (j=0;j<g;j++)
66         {
67             k=k | a[num[j]];
68             use[k]=1;
69         }
70     }
71     g=0;
72     for (i=0;i<1048576;i++)
73         if (use[i])
74             g++;
75     printf("%ld",g);
76     return 0;
77 }

F 選值 > 25960795

先對數排序

用兩個變量,求從一個數開始,大於等於該數且差值小於等於d的數的最遠編號,這個編號一直是遞增的,所以O(n)。

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <set>
 6 #include <map>
 7 #include <list>
 8 #include <stack>
 9 #include <queue>
10 #include <vector>
11 #include <algorithm>
12 #include <iostream>
13 using namespace std;
14 #define ll long long
15 const long maxn=1e5+5;
16 const ll mod=1e9+7;
17 
18 long a[maxn];
19 
20 int main()
21 {
22     long n,d,i,k;
23     long long r=0,g;
24     scanf("%ld%ld",&n,&d);
25     for (i=1;i<=n;i++)
26         scanf("%ld",&a[i]);
27     k=1;
28     for (i=1;i<=n;i++)
29     {
30         while (k!=n && a[k+1]-a[i]<=d)
31             k++;
32         g=k-i;
33         r=r+g*(g-1)/2;
34     }
35     printf("%lld",r);
36     return 0;
37 }

或者

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <set>
 6 #include <map>
 7 #include <list>
 8 #include <stack>
 9 #include <queue>
10 #include <vector>
11 #include <algorithm>
12 #include <iostream>
13 using namespace std;
14 #define ll long long
15 const long maxn=1e5+5;
16 const ll mod=1e9+7;
17  
18 long a[maxn];
19  
20 int main()
21 {
22     long n,d,i,j,k;
23     long long r=0,g1,g2;
24     scanf("%ld%ld",&n,&d);
25     for (i=1;i<=n;i++)
26         scanf("%ld",&a[i]);
27     k=1;
28     for (i=1;i<=n;i++)
29     {
30         j=i;
31         while (j!=n && a[j+1]==a[i])
32             j++;
33         k=max(k,j);
34         while (k!=n && a[k+1]-a[i]<=d)
35             k++;
36         g1=j-i+1;
37         g2=k-j;
38         if (g1>=3)
39             r=r+g1*(g1-1)*(g1-2)/6;
40         if (g1>=2 && g2>=1)
41             r=r+g1*(g1-1)/2*g2;
42         if (g1>=1 && g2>=2)
43             r=r+g1*g2*(g2-1)/2;
44         i=j;
45     }
46     printf("%lld",r);
47     return 0;
48 }

牛客練習賽16