每天一道算法题(2/16—3/10)

本小妞迷上赌 提交于 2020-05-08 06:13:48

考研狗的日常休闲活动。

Update:3/11日停更,刷PAT的题目去了。

 

2019/2/16 

CF 1113A Sasha and His Trip

第一站先把油桶加满,后面每到一站判断油箱内的油能否支持开到最后,不能的话加一升油(花费$i$元)。思路就是尽量在前面站加油。

 1 #include <set>
 2 #include <map>
 3 #include <queue>
 4 #include <deque>
 5 #include <stack>
 6 #include <cmath>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <string>
10 #include <cstring>
11 #include <fstream>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 
16 #define eps 1e-8
17 #define pb push_back
18 #define PI acos(-1.0)
19 #define INF 0x3f3f3f3f
20 #define clr(a,b) memset(a,b,sizeof(a)
21 #define bugc(_) cerr << (#_) << " = " << (_) << endl
22 #define FAST_IO ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
23 
24 typedef long long ll;
25 typedef unsigned long long ull;
26 
27 int main(){
28     FAST_IO;
29     int n,v,cost=0;
30     cin>>n>>v;
31     if(v>=n-1){
32         cout<<n-1<<endl;
33         return 0;
34     }
35     cout<<v+(2+n-v)*(n-v-1)/2<<endl;
36     return 0;
37 }
View Code

 

2019/2/17

CF 1113B Sasha and Magnetic Machines

两个数中乘上$x$的一定是所有数中最小的,再枚举剩下的数($ai<=100$),每个数再枚举其因子,过程中更新答案。

 1 #include <set>
 2 #include <map>
 3 #include <queue>
 4 #include <deque>
 5 #include <stack>
 6 #include <cmath>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <string>
10 #include <cstring>
11 #include <fstream>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 
16 #define eps 1e-8
17 #define pb push_back
18 #define PI acos(-1.0)
19 #define INF 0x3f3f3f3f
20 #define clr(a,b) memset(a,b,sizeof(a)
21 #define bugc(_) cerr << (#_) << " = " << (_) << endl
22 #define FAST_IO ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
23 
24 typedef long long ll;
25 typedef unsigned long long ull;
26 const int N=5e4+10;
27 int a[N];
28 
29 int main(){
30     FAST_IO;
31     int n,sum=0,ans=INF;
32     cin>>n;
33     for(int i=1;i<=n;i++) cin>>a[i],sum+=a[i];
34     ans=sum;
35     sort(a+1,a+1+n);
36     for(int i=2;i<=n;i++){
37         for(int j=1;j*j<=a[i];j++){
38             if(a[i]%j==0){
39                 ans=min(ans,sum-a[1]-a[i]+a[1]*j+a[i]/j);
40             }
41         }
42     }
43     cout<<ans<<endl;
44     return 0;
45 }
View Code

 

2/18

CF 1113C Sasha and a Bit of Relax

$pre[i]$表示前缀异或值。若$pre[i]$和$pre[j]$相同,且$i<j$,说明$(i,j]$异或值为0,那么从中取出任意个进行异或得到的值 和 剩下的数异或得到的值相等,所以只要保证$j-i$为偶数即可。

操作的话,奇数位置和偶数位置分别记录下即可。

 1 #include <set>
 2 #include <map>
 3 #include <queue>
 4 #include <deque>
 5 #include <stack>
 6 #include <cmath>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <string>
10 #include <cstring>
11 #include <fstream>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 
16 #define eps 1e-8
17 #define pb push_back
18 #define PI acos(-1.0)
19 #define INF 0x3f3f3f3f
20 #define clr(a,b) memset(a,b,sizeof(a)
21 #define bugc(_) cerr << (#_) << " = " << (_) << endl
22 #define FAST_IO ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
23 
24 typedef long long ll;
25 typedef unsigned long long ull;
26 map <ll,ll> odd,even;
27 
28 int main(){
29     FAST_IO;
30     ll n,num,tmp=0,ans=0,mx=0;
31     cin>>n;
32     even[0]++;
33     for(ll i=1;i<=n;i++){
34         cin>>num;
35         tmp=tmp^num;
36         mx=max(mx,tmp);
37         if(i%2==1) odd[tmp]++;
38         else even[tmp]++;
39     }
40     for(ll i=0;i<=mx;i++){
41         ans+=odd[i]*(odd[i]-1)/2;
42         ans+=even[i]*(even[i]-1)/2;
43     }
44     cout<<ans<<endl;
45     return 0;
46 }
View Code

 

2/19

CF 1113D Sasha and One More Name

长度为n的字符串,大于等于n-1个相同字符Impossible;切一刀的情况,每个位置遍历一下,找到符合条件;剩余的情况都是切两刀的。

 1 #include <set>
 2 #include <map>
 3 #include <queue>
 4 #include <deque>
 5 #include <stack>
 6 #include <cmath>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <string>
10 #include <cstring>
11 #include <fstream>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 
16 #define eps 1e-8
17 #define pb push_back
18 #define PI acos(-1.0)
19 #define INF 0x3f3f3f3f
20 #define clr(a,b) memset(a,b,sizeof(a)
21 #define bugc(_) cerr << (#_) << " = " << (_) << endl
22 #define FAST_IO ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
23 
24 typedef long long ll;
25 typedef unsigned long long ull;
26 map <char,int> mp;
27 
28 bool check(string s,string p){
29     if(s==p) return false;
30     int m=s.size();
31     for(int i=0;i<m/2;i++){
32         if(s[i]!=s[m-1-i]) return false;
33     }
34     return true;
35 }
36 
37 int main(){
38     FAST_IO;
39     string str,s1,s2,s;
40     cin>>str;
41     int n=str.size();
42     for(int i=0;i<n;i++){
43         char c=str[i];
44         mp[c]++;
45         if(mp[c]>=n-1){
46             cout<<"Impossible"<<endl;
47             return 0;
48         }
49     }
50     for(int i=1;i<n;i++){
51         s1=str.substr(0,i);
52         s2=str.substr(i,n-i);
53         s=s2+s1;
54         if(check(s,str)){
55             cout<<1<<endl;
56             return 0;
57         }
58     }
59     cout<<2<<endl;
60     return 0;
61 }
View Code

 

2/20

CF 1117A Best Subsegment

找最长连续最大数串。

 1 #include <set>
 2 #include <map>
 3 #include <queue>
 4 #include <deque>
 5 #include <stack>
 6 #include <cmath>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <string>
10 #include <cstring>
11 #include <fstream>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 
16 #define eps 1e-8
17 #define pb push_back
18 #define PI acos(-1.0)
19 #define INF 0x3f3f3f3f
20 #define clr(a,b) memset(a,b,sizeof(a)
21 #define bugc(_) cerr << (#_) << " = " << (_) << endl
22 #define FAST_IO ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
23 
24 typedef long long ll;
25 typedef unsigned long long ull;
26 const int N=1e5+10;
27 int a[N];
28 
29 int main(){
30     FAST_IO;
31     int n,mx=0,ans=0;
32     cin>>n;
33     for(int i=1;i<=n;i++) cin>>a[i],mx=max(mx,a[i]);
34     for(int i=1;i<=n;i++){
35         if(a[i]==mx){
36             int cnt=1,j=i;
37             for(j=i+1;j<=n;j++){
38                 if(a[j]==a[i]) cnt++;
39                 else break;
40             }
41             i=j;
42             ans=max(ans,cnt);
43         }
44     }
45     cout<<ans<<endl;
46     return 0;
47 }
View Code

CF 1117B Emotes

配k个最大值和1个次大值为一组,m个位置一组一组地填进去,剩下的再用最大值填。

 1 #include <set>
 2 #include <map>
 3 #include <queue>
 4 #include <deque>
 5 #include <stack>
 6 #include <cmath>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <string>
10 #include <cstring>
11 #include <fstream>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 
16 #define eps 1e-8
17 #define pb push_back
18 #define PI acos(-1.0)
19 #define INF 0x3f3f3f3f
20 #define clr(a,b) memset(a,b,sizeof(a)
21 #define bugc(_) cerr << (#_) << " = " << (_) << endl
22 #define FAST_IO ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
23 
24 typedef long long ll;
25 typedef unsigned long long ull;
26 const int N=2e5+10;
27 ll a[N];
28 
29 int main(){
30     FAST_IO;
31     ll n,m,k;
32     cin>>n>>m>>k;
33     for(ll i=1;i<=n;i++) cin>>a[i];
34     sort(a+1,a+1+n);
35     ll t=m/(k+1);
36     cout<<t*(k*a[n]+a[n-1])+(m%(k+1))*a[n]<<endl;
37     return 0;
38 }
View Code

 

2/21

CF 1117C Magic Ship

二分下答案。先统计mid天靠风能跑到哪个位置,然后去凑。注意left==right的时候也要判断下,不然会漏。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 typedef long long ll;
 8 const int N=1e5+10;
 9 char s[N];
10 ll n,x1,y1,x2,y2;
11 ll L=0,R=0,U=0,D=0;
12 
13 bool check(ll mid){
14     ll time=mid/n;
15     ll l=time*L,r=time*R,u=time*U,d=time*D;
16     for(int i=1;i<=(mid%n);i++){
17         if(s[i]=='L') l++;
18         else if(s[i]=='R') r++;
19         else if(s[i]=='U') u++;
20         else if(s[i]=='D') d++;
21     }
22     //r
23     ll p=0;
24     if(x2>=x1){
25         p=(x2-x1)-(r-l);
26         if(mid<abs(p)) return false;
27         else mid-=abs(p);
28     }
29     //l
30     else{
31         p=(x1-x2)-(l-r);
32         if(mid<abs(p)) return false;
33         else mid-=abs(p);
34     }
35     //u
36     if(y2>=y1){
37         p=(y2-y1)-(u-d);
38         if(mid<abs(p)) return false;
39         else mid-=abs(p);
40     }
41     //d
42     else{
43         p=(y1-y2)-(d-u);
44         if(mid<abs(p)) return false;
45         else mid-=abs(p);
46     }
47     return true;
48 }
49 
50 int main(){
51     scanf("%lld%lld%lld%lld%lld",&x1,&y1,&x2,&y2,&n);
52     scanf("%s",s+1);
53     for(int i=1;i<=n;i++){
54         if(s[i]=='L') L++;
55         else if(s[i]=='R') R++;
56         else if(s[i]=='U') U++;
57         else if(s[i]=='D') D++;
58     }
59     ll mid,left=0,right=1e18,ans=1e18;
60     while(left<=right){
61         mid=(left+right)/2;
62         if(check(mid)) ans=min(ans,mid),right=mid-1;
63         else left=mid+1;
64     }
65     if(ans==1e18) printf("-1\n");
66     else printf("%lld\n",ans);
67     return 0;
68 }
View Code

 

2/22

CF 1118A Water Buying

判断下2a和b的大小。

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 typedef long long ll;
 7 
 8 int main(){
 9     int q;
10     cin>>q;
11     while(q--){
12         ll n,a,b;
13         cin>>n>>a>>b;
14         if(2*a<=b) cout<<n*a<<endl;
15         else{
16             cout<<b*(n/2)+(n%2)*a<<endl;
17         }
18     }
19     return 0;
20 }
View Code

CF 1118B Tanya and Candies

奇数和偶数位置前缀分别记录下,如果某个位置拿掉,那么该位置的前面奇数偶数位置不变,后面奇变偶,偶变奇。

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 const int N=2e5+10;
 7 int a[N],odd[N],even[N];
 8 
 9 int main(){
10     int n,ans=0;
11     scanf("%d",&n);
12     for(int i=1;i<=n;i++){
13         scanf("%d",&a[i]);
14         odd[i]=odd[i-1];
15         even[i]=even[i-1];
16         if(i%2) odd[i]+=a[i];
17         else even[i]+=a[i];
18     }
19     for(int i=1;i<=n;i++){
20         int sum1=odd[i-1]+even[n]-even[i];
21         int sum2=even[i-1]+odd[n]-odd[i];
22         if(sum1==sum2) ans++;
23     }
24     printf("%d\n",ans);
25     return 0;
26 }
View Code

 

2/23

CF 1118C Palindromic Matrix

使劲模拟,注意细节,大力出奇迹。

  1 #include <map>
  2 #include <cstdio>
  3 #include <iostream>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 const int N=2010;
  8 int a[N],num[N];
  9 int ans[N][N];
 10 bool vis[N];
 11 map <int,int> m;
 12 
 13 int main(){
 14     int n,cnt=0;
 15     scanf("%d",&n);
 16     for(int i=1;i<=n*n;i++) scanf("%d",&a[i]),m[a[i]]++;
 17     for(int i=1;i<=n*n;i++){
 18         if(!vis[a[i]]){
 19             num[++cnt]=a[i];
 20             vis[a[i]]=1;
 21         }
 22     }
 23 
 24     //n/2
 25     int x=1,y=1;
 26     for(int i=1;i<=cnt;i++){
 27         if(m[num[i]]%2){
 28             if(n%2==0) {printf("NO\n");return 0;}
 29             else{
 30                 if(ans[n/2+1][n/2+1]!=0) {printf("NO\n");return 0;}
 31                 else{
 32                     ans[n/2+1][n/2+1]=num[i];
 33                     m[num[i]]--;
 34                 }
 35             }
 36         }
 37         if(n%2==0&&m[num[i]]%4!=0) {printf("NO\n");return 0;}
 38         int time=m[num[i]]/4;
 39         for(int j=1;j<=time;j++){
 40             if(y>n/2){
 41                 x++;
 42                 y=1;
 43                 if(x>n/2) break;
 44             }
 45             ans[x][y]=ans[x][n-y+1]=ans[n-x+1][y]=ans[n-x+1][n-y+1]=num[i];
 46             y++;
 47             m[num[i]]-=4;
 48         }
 49         if(x>n/2) break;
 50     }
 51 
 52     //奇数单独补充
 53     x=1;y=n/2+1;
 54     for(int i=1;i<=cnt;i++){
 55         int time=m[num[i]]/2;
 56         //cout<<num[i]<<" "<<m[num[i]]<<endl;
 57         for(int j=1;j<=time;j++){
 58             ans[x][y]=ans[n-x+1][y]=num[i];
 59             x++;
 60             m[num[i]]-=2;
 61             if(x==(n/2+1)) break;
 62         }
 63         if(x==n/2+1) break;
 64     }
 65 
 66     x=n/2+1;y=1;
 67     for(int i=1;i<=cnt;i++){
 68         int time=m[num[i]]/2;
 69         //cout<<num[i]<<" "<<m[num[i]]<<endl;
 70         for(int j=1;j<=time;j++){
 71             ans[x][y]=ans[x][n-y+1]=num[i];
 72             y++;
 73             m[num[i]]-=2;
 74             if(y==(n/2+1)) break;
 75         }
 76         if(y==(n/2+1)) break;
 77     }
 78 
 79     for(int i=1;i<=cnt;i++){
 80          if(m[num[i]]%2){
 81             if(n%2==0) {printf("NO\n");return 0;}
 82             else{
 83                 if(ans[n/2+1][n/2+1]!=0) {printf("NO\n");return 0;}
 84                 else{
 85                     ans[n/2+1][n/2+1]=num[i];
 86                     m[num[i]]--;
 87                 }
 88             }
 89         }
 90     }
 91 
 92     //检测
 93     for(int i=1;i<=n;i++)
 94     for(int j=1;j<=n;j++){
 95         if(ans[i][j]==0) {printf("NO\n");return 0;}
 96     }
 97 
 98     printf("YES\n");
 99     for(int i=1;i<=n;i++){
100         for(int j=1;j<=n;j++){
101             printf("%d",ans[i][j]);
102             if(j==n) printf("\n");
103             else printf(" ");
104         }
105     }
106     return 0;
107 }
View Code

 

2/24

CF 1118F1 Tree Cutting (Easy Version)

DFS遍历下树,以父亲节点和儿子节点分开,判断儿子节点的子树是否拿全了其中一种颜色,并且没有另一种颜色。

 1 #include <vector>
 2 #include <cstdio>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int N=3e5+10;
 8 int a[N],b[N],r[N],n,ans=0;
 9 vector <int> E[N];
10 
11 void dfs(int x,int fa){
12     if(a[x]==1) b[x]++;
13     else if(a[x]==2) r[x]++;
14     for(int i=0;i<E[x].size();i++){
15         int u=E[x][i];
16         if(u!=fa){
17             dfs(u,x);
18             b[x]+=b[u];
19             r[x]+=r[u];
20             if( (b[u]==b[0]&&!r[u]) || (r[u]==r[0]&&!b[u]) ) ans++;
21         }
22     }
23 }
24 
25 int main(){
26     scanf("%d",&n);
27     for(int i=1;i<=n;i++){
28         scanf("%d",&a[i]);
29         if(a[i]==1) b[0]++;
30         else if(a[i]==2) r[0]++;
31     }
32     for(int i=1;i<n;i++){
33         int u,v;
34         scanf("%d%d",&u,&v);
35         E[u].push_back(v);
36         E[v].push_back(u);
37     }
38     dfs(1,0);
39     printf("%d\n",ans);
40     return 0;
41 }
View Code

 

2/25

CF 1118D1 Coffee and Coursework (Easy version)

暴力枚举答案,时间复杂度O(n^2)

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 int a[110];
 8 const int INF=0x3f3f3f3f;
 9 int n,m,sum=0,ans=INF;
10 
11 bool check(int k){
12     int cnt=0,id=0,cost=0;
13     for(int i=1;i<=n;i++){
14         id++;
15         if(id>k) id=1,cost++;
16         cnt+=a[i]-cost;
17         if(cnt>=m) return true;
18     }
19     return false;
20 }
21 
22 bool cmp(int x,int y){
23     return x>y;
24 }
25 
26 int main(){
27     scanf("%d%d",&n,&m);
28     for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum+=a[i];
29     sort(a+1,a+1+n,cmp);
30     for(int i=n;i>=1;i--){
31         if(check(i)) ans=min(ans,i);
32     }
33     if(ans==INF) printf("-1\n");
34     else printf("%d\n",ans);
35     return 0;
36 }
View Code

CF 1118D2 Coffee and Coursework (Hard Version)

二分下答案,时间复杂度O(nlogn)

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 typedef long long ll;
 8 const int N=2e5+10;
 9 ll a[N];
10 int n,m,ans=N;
11 
12 bool check(int k){
13     int id=0;
14     ll cnt=0,cost=0;
15     for(int i=1;i<=n;i++){
16         id++;
17         if(id>k) id=1,cost++;
18         cnt+=a[i]-cost;
19         if(cnt>=m) return true;
20     }
21     return false;
22 }
23 
24 bool cmp(ll x,ll y){
25     return x>y;
26 }
27 
28 int main(){
29     scanf("%d%d",&n,&m);
30     for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
31     sort(a+1,a+1+n,cmp);
32     int l=1,r=n;
33     while(l<=r){
34         int mid=(l+r)/2;
35         if(check(mid)) ans=min(ans,mid),r=mid-1;
36         else l=mid+1;
37     }
38     if(ans==N) printf("-1\n");
39     else printf("%d\n",ans);
40     return 0;
41 }
View Code

 

2/26

CF 1118E Yet Another Ball Problem

左右两列都搞1到k,然后把右边那列上移。最多能有k*(k-1)种,举个例子

1 1   1 2  1  3  

2 2   2 3  2  1

3 3   3 1  3  2

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 int main(){
 7     int n,k;
 8     scanf("%d%d",&n,&k);
 9     if(1LL*n>1LL*(k-1)*k) {printf("NO\n");return 0;}
10     printf("YES\n");
11     for(int i=2;i<=k;i++){
12         int num=i;
13         for(int j=1;j<=k;j++){
14             printf("%d %d\n",j,num++);
15             n--;
16             if(n==0) return 0;
17             if(num==k+1) num=1;
18         }
19     }
20     return 0;
21 }
View Code

 

2/27

CF 1131F Asya And Kittens

并查集维护下右边。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int N=150000+10;
 8 int fa[N],r[N],ed[N];
 9 
10 int fi(int x){
11     return x==fa[x]?x:fa[x]=fi(fa[x]);
12 }
13 
14 int main(){
15     for(int i=1;i<=N;i++) fa[i]=ed[i]=i;
16     int n;
17     scanf("%d",&n);
18     for(int i=1;i<n;i++){
19         int u,v;
20         scanf("%d%d",&u,&v);
21         int fx=fi(u),fy=fi(v);
22         fa[fy]=fx;r[ed[fx]]=fy;ed[fx]=ed[fy];
23     }
24     for(int i=1;i<=n;i++){
25         if(fa[i]==i){
26             for(int j=i;j;j=r[j]) printf("%d ",j);
27             return 0;
28         }
29     }
30     return 0;
31 }
View Code

 

2/28

CF 1131D Gourmet choice

除去$=$的条件就是道裸的拓扑排序,$=$的情况只要用并查集缩下点就可以了。

 1 #include <queue>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 const int N=1234;
 9 char s[N][N];
10 int n,m,fa[2*N],in[2*N],ans[2*N];
11 vector <int> E[2*N];
12 
13 int fi(int x){
14     return x==fa[x]?x:fa[x]=fi(fa[x]);
15 }
16 
17 void init(){
18     for(int i=0;i<2*N;i++) fa[i]=i;
19 }
20 
21 bool toposort(){
22     queue <int> Q;
23     for(int i=1;i<=n+m;i++) if(i==fi(i)&&in[i]==0) Q.push(i),ans[i]=1;
24     while(!Q.empty()){
25         int u=Q.front();
26         Q.pop();
27         for(int i=0;i<E[u].size();i++){
28             int v=E[u][i];
29             in[v]--;
30             if(in[v]==0) Q.push(v),ans[v]=ans[u]+1;
31         }
32     }
33     for(int i=1;i<=n+m;i++) if(ans[fi(i)]==0) return false;
34     return true;
35 }
36 
37 int main(){
38     init();
39     scanf("%d%d",&n,&m);
40     for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
41     for(int i=1;i<=n;i++)
42     for(int j=1;j<=m;j++)
43     if(s[i][j]=='=') fa[fi(j+n)]=fa[fi(i)];
44 
45     for(int i=1;i<=n;i++)
46     for(int j=1;j<=m;j++)
47     if(s[i][j]=='<') E[fi(i)].push_back(fi(n+j)),in[fi(n+j)]++;
48     else if(s[i][j]=='>') E[fi(n+j)].push_back(fi(i)),in[fi(i)]++;
49 
50     if(!toposort()) printf("No\n");
51     else{
52         printf("Yes\n");
53         for(int i=1;i<=n;i++) printf("%d ",ans[fi(i)]);
54         printf("\n");
55         for(int i=1;i<=m;i++) printf("%d ",ans[fi(n+i)]);
56     }
57     return 0;
58 }
View Code

 

2019/3/1

CF 1130D1 Toy Train (Simplified)

先把每个点处理,计算该点运送完需要的时间;遍历每个点时给它绕一圈,找到时间最长的那个,那个就是把所有运送完所需的时间。注意如果没有货物,需要跳过该点。

 1 #include <vector>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 const int N=222;
 9 const int INF=0x3f3f3f3f;
10 int ans[N];
11 vector <int> s[N];
12 
13 int main(){
14     int n,m;
15     scanf("%d%d",&n,&m);
16     for(int i=1;i<=m;i++){
17         int a,b;
18         scanf("%d%d",&a,&b);
19         s[a].push_back(b);
20     }
21     for(int i=1;i<=n;i++){
22         int mi=INF;
23         for(int j=0;j<s[i].size();j++){
24             int u=s[i][j];
25             if(u>=i) mi=min(mi,u-i);
26             else mi=min(mi,n-i+u);
27         }
28         if(mi!=INF) ans[i]=n*(s[i].size()-1)+mi;
29     }
30     for(int i=1;i<=n;i++){
31         int res=0,time=n,k=i,cnt=0;
32         while(time--){
33             //注意
34             if(ans[k]!=0) res=max(res,ans[k]+cnt);
35             k++;
36             if(k==n+1) k=1;
37             cnt++;
38         }
39         printf("%d ",res);
40     }
41     return 0;
42 }
View Code

 

2019/3/2

CF 1130D2 Toy Train

和上题一样,改下long long就可以了,发现自己一开始写的就挺优的,O(n^2)。

 1 #include <vector>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 const int N=5555;
 9 typedef long long ll;
10 ll ans[N];
11 vector <int> s[N];
12 
13 int main(){
14     int n,m;
15     scanf("%d%d",&n,&m);
16     for(int i=1;i<=m;i++){
17         int a,b;
18         scanf("%d%d",&a,&b);
19         s[a].push_back(b);
20     }
21     for(int i=1;i<=n;i++){
22         ll mi=1e18;
23         for(int j=0;j<s[i].size();j++){
24             int u=s[i][j];
25             if(u>=i) mi=min(mi,1LL*(u-i));
26             else mi=min(mi,1LL*(n-i+u));
27         }
28         if(mi!=1e18) ans[i]=1LL*n*(s[i].size()-1)+mi;
29     }
30     for(int i=1;i<=n;i++){
31         ll res=0;
32         int time=n,k=i,cnt=0;
33         while(time--){
34             if(ans[k]!=0) res=max(res,ans[k]+cnt);
35             k++;
36             if(k==n+1) k=1;
37             cnt++;
38         }
39         printf("%lld ",res);
40     }
41     return 0;
42 }
View Code

 

2019/3/3

CF 1114C Trailing Loves (or L'oeufs?)

b分解质因子,每个质因子对n!求指数,要使b全部符合,那么最少的那个指数就为答案。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 typedef long long ll;
 8 ll n,b,ans=1e18;
 9 
10 void cal(ll num,ll cnt){
11     ll tmp=1,res=0;
12     while(tmp<=n/num){
13         tmp*=num;
14         res+=n/tmp;
15     }
16     ans=min(ans,res/cnt);
17 }
18 
19 int main(){
20     scanf("%lld%lld",&n,&b);
21     for(ll i=2;i*i<=b;i++){
22         if(b%i==0){
23             ll cnt=0;
24             while(b%i==0){
25                 b/=i;
26                 cnt++;
27             }
28             cal(i,cnt);
29         }
30     }
31     if(b>1) cal(b,1);
32     printf("%lld\n",ans);
33     return 0;
34 }
View Code

 

2019/3/4

CF 1114D Flood Fill(区间DP)

$dp[l][r][0]$表示以c[l]为整块颜色的最小花费,$dp[l][r][1]$表示以c[r]为整块颜色的最小花费。

转移方程:

$dp[l][r][0]=min(dp[l+1][r][0]+(c[l]!=c[l+1]),dp[l+1][r][1]+(c[l]!=c[r]))$
$dp[l][r][1]=min(dp[l][r-1][0]+(c[l]!=c[r]),dp[l][r-1][1]+(c[r-1]!=c[r]))$

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int N=5555;
 8 int c[N],dp[N][N][2];
 9 
10 int main(){
11     memset(dp,0x3f,sizeof(dp));
12     int n;
13     scanf("%d",&n);
14     for(int i=1;i<=n;i++){
15         scanf("%d",&c[i]);
16         dp[i][i][0]=dp[i][i][1]=0;
17     }
18     for(int len=2;len<=n;len++){
19         for(int l=1;l<=n;l++){
20             int r=l+len-1;
21             if(r>n) break;
22             dp[l][r][0]=min(dp[l+1][r][0]+(c[l]!=c[l+1]),dp[l+1][r][1]+(c[l]!=c[r]));
23             dp[l][r][1]=min(dp[l][r-1][0]+(c[l]!=c[r]),dp[l][r-1][1]+(c[r-1]!=c[r]));
24         }
25     }
26     printf("%d\n",min(dp[1][n][0],dp[1][n][1]));
27     return 0;
28 }
View Code

 

2019/3/5

CF 1111C Creative Snap

DFS二分区间,比较继续二分后的代价和当前代价大小。区间长度问题可以二分区间。整体就是二分套二分啦。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int N = 1e5 + 10;
 8 int n, k, A, B;
 9 int a[N];
10 typedef long long ll;
11 
12 ll dfs(int l, int r){
13     int len = upper_bound(a + 1, a + 1 + k, r) - upper_bound(a + 1, a + 1 + k, l - 1 );
14     ll res = 0;
15     if(len) {
16         res = 1LL * B * len * (r - l + 1);
17     } else {
18         return A;
19     }
20     if(l == r) return res;
21     int mid = (l + r) / 2;
22     res = min(res, dfs(l, mid) + dfs(mid + 1, r));
23     return res;
24 }
25 
26 int main() {
27     scanf("%d %d %d %d", &n, &k, &A, &B);
28     for(int i = 1; i <= k; i++) {
29         scanf("%d", &a[i]);
30     }
31     sort(a + 1, a + 1 + k);
32     printf("%lld\n", dfs(1, (1<<n) ));
33     return 0;
34 }
View Code

 

2019/3/6

CF 1111B Average Superhero Gang Power

排序后,从后往前累加,在当前数之前的数都删掉,剩下来的m给当前和之后的数平均分下去,如果平均分下去大于k,那就只给k,否则就可以全部分下去,更新下答案。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 typedef long long ll;
 8 const int N = 1e5 + 10;
 9 ll a[N];
10 
11 int main() {
12     double ans = 0;
13     int n, k, m;
14     scanf("%d %d %d", &n, &k, &m);
15     for(int i = 1; i <= n; i++) {
16         scanf("%lld", &a[i]);
17     }
18     sort(a + 1, a + 1 + n);
19     ll sum = 0;
20     for(int i = n; i >= 1; i--) {
21         sum += a[i];
22         if(m >= i - 1 ) {
23             int new_m = m - i + 1;
24             int ave = new_m / (n - i + 1);
25             if(ave >= k) {
26                 ans = max(ans, 1.0 * sum / (n - i + 1) + 1.0 * k);
27             } else {
28                 ans = max(ans, (1.0 * sum + 1.0 * new_m) / (n - i + 1) );
29             }
30         }
31     }
32     printf("%.10f", ans);
33     return 0;
34 }
View Code

 

2019/3/7

CF 1132 Painting the Fence

先枚举下第一个人画的区间,处理完后把第二个人画的区间用前缀处理下。最后遍历下所有人,更新答案。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int N = 5555;
 8 int p[N], l[N], r[N], cnt[N];
 9 
10 int main() {
11     int n, q, ans = 0, res = 0;
12     scanf("%d %d", &n, &q);
13     for(int i = 1; i <= q; i++) {
14         scanf("%d %d", &l[i], &r[i]);
15         for(int j = l[i]; j <= r[i]; j++) {
16             p[j]++;
17             if(p[j] == 1) ans++;
18         }
19     }
20     for(int i = 1; i <= q; i++) {
21         int sum = ans;
22         for(int k = l[i]; k <= r[i]; k++) {
23             p[k]--;
24             if(p[k] == 0) sum--;
25         }
26         for(int k = 1; k <= n; k++) {
27             if(p[k] == 1) cnt[k] = 1;
28             else cnt[k] = 0;
29             cnt[k] += cnt[k-1];
30         }
31         for(int k = i + 1; k <= q; k++) {
32             res = max(res, sum - (cnt[ r[k] ] - cnt[ l[k] - 1 ]));
33         }
34         for(int k = l[i]; k <= r[i]; k++) {
35             p[k]++;
36         }
37     }
38     printf("%d", res);
39     return 0;
40 }
View Code

 

2019/3/8

CF 1107D Compression

先暴力枚举出原来的n x n矩阵,然后对能整除n的数字进行判断,每一块负责的是否符合要求。更新最大的答案。(矩阵压缩)

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int N = 6666;
 8 typedef long long ll;
 9 int n, ans = 0;
10 string str, s[N];
11 
12 string cal(char ch) {
13     if(ch == '0') return "0000";
14     if(ch == '1') return "0001";
15     if(ch == '2') return "0010";
16     if(ch == '3') return "0011";
17     if(ch == '4') return "0100";
18     if(ch == '5') return "0101";
19     if(ch == '6') return "0110";
20     if(ch == '7') return "0111";
21     if(ch == '8') return "1000";
22     if(ch == '9') return "1001";
23     if(ch == 'A') return "1010";
24     if(ch == 'B') return "1011";
25     if(ch == 'C') return "1100";
26     if(ch == 'D') return "1101";
27     if(ch == 'E') return "1110";
28     if(ch == 'F') return "1111";
29 }
30 
31 bool check(int k) {
32     for(int x = 0; x < n; x+=k) {
33         for(int y = 0; y < n; y+=k) {
34             char ch = s[x][y];
35             for(int i = x; i < x + k; i++) {
36                 for(int j = y; j < y + k; j++) {
37                     if(s[i][j] != ch) return false;
38                 }
39             }
40         }
41     }
42     return true;
43 }
44 
45 int main() {
46     ios::sync_with_stdio(false);
47     cin >> n;
48     for(int i = 0; i < n; i++) {
49         cin >> str;
50         for(int j = 0; j < str.size(); j++) {
51             s[i] = s[i] + cal(str[j]);
52         }
53     }
54     for(int i = 1; i <= n; i++) {
55         if(n % i == 0) {
56             if(check(i)) ans = i;
57         }
58     }
59     cout << ans << endl;
60     return 0;
61 }
View Code

 

2019/3/9

CF 1133F1 Spanning Tree with Maximum Degree

从度数最大的点BFS一下即可。

 1 #include <queue>
 2 #include <vector>
 3 #include <cstdio>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 const int N = 2e5 + 10;
 9 int n, m;
10 int d[N];
11 bool vis[N];
12 vector<int> E[N];
13 
14 void bfs(int st) {
15     queue<int> Q;
16     Q.push(st);
17     vis[st] = 1;
18     while(!Q.empty()) {
19         int u = Q.front();
20         Q.pop();
21         for(int i = 0; i < E[u].size(); i++) {
22             int v = E[u][i];
23             if(!vis[v]) {
24                 printf("%d %d\n", u, v);
25                 vis[v] = 1;
26                 Q.push(v);
27             }
28         }
29     }
30 }
31 
32 int main() {
33     scanf("%d %d", &n, &m);
34     for(int i = 1; i <= m; i++) {
35         int u, v;
36         scanf("%d %d", &u, &v);
37         E[u].push_back(v);
38         E[v].push_back(u);
39         d[u]++;d[v]++;
40     }
41     int mx = 0, id = 0;
42     for(int i = 1; i <= n; i++) {
43         if(d[i] > mx) {
44             mx = d[i];
45             id = i;
46         }
47     }
48     bfs(id);
49     return 0;
50 }
View Code

 

2019/3/10

CF 1137A Skyscrapers

离散化。

 1 #include <queue>
 2 #include <vector>
 3 #include <cstdio>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 const int N = 1234;
 9 int a[N][N];
10 vector<int> r[N],c[N];
11 
12 int main() {
13     int n, m;
14     scanf("%d %d", &n, &m);
15     for(int i = 0; i < n; i++) {
16         for(int j = 0; j < m; j++) {
17             scanf("%d", &a[i][j]);
18             r[i].push_back(a[i][j]);
19             c[j].push_back(a[i][j]);
20         }
21     }
22     for(int i = 0; i < n; i++) {
23         sort(r[i].begin(), r[i].end());
24         r[i].erase(unique(r[i].begin(), r[i].end()), r[i].end());
25     }
26     for(int i = 0; i < m; i++) {
27         sort(c[i].begin(), c[i].end());
28         c[i].erase(unique(c[i].begin(), c[i].end()), c[i].end());
29     }
30     for(int i = 0; i < n; i++) {
31         for(int j = 0; j < m; j++) {
32             int p1 = lower_bound(r[i].begin(), r[i].end(), a[i][j]) - r[i].begin();
33             int p2 = lower_bound(c[j].begin(), c[j].end(), a[i][j]) - c[j].begin();
34             int p3 = r[i].end() - lower_bound(r[i].begin(), r[i].end(), a[i][j]);
35             int p4 = c[j].end() - lower_bound(c[j].begin(), c[j].end(), a[i][j]);
36             printf("%d", max(p1, p2) + max(p3, p4));
37             if(j == m - 1) printf("\n");
38             else printf(" ");
39         }
40     }
41     return 0;
42 }
View Code

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!