Educational Codeforces Round 54

这套题不难,但是场上数据水,导致有很多叉点

A.

因为是让求删掉一个后字典序最小,那么当a[i]>a[i+1]的时候,删掉a[i]一定最优!这个题有个叉点,当扫完一遍如果没有满足条件的,就删去最后一个字符。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <set>
 6 #include <map>
 7 #include <vector>
 8 #include <queue>
 9 #include <cmath>
10 #include <cstdlib>
11 #include <stack>
12 
13 using namespace std;
14 const double eps = 1e-6;
15 const int MOD=1e9+7;
16 typedef long long LL;
17 typedef unsigned long long ull;
18 const int INF=2147000000;
19 const LL inf = 1e18;
20 LL gcd(LL a,LL b){
21     if(!b)return a;
22     return gcd(b,a%b);
23 }
24 LL lcm(LL a,LL b){
25     return a/gcd(a,b)*b;
26 }
27 const int maxn=2e5+100;
28 char s[maxn];
29 int n;
30 int main(){
31     scanf("%d",&n);
32     scanf("%s",s);
33     int pos=-1;
34     for(int i=0;i<n-1;i++){
35         if(s[i+1]<s[i]){
36             pos=i;
37             break;
38         }
39     }
40     if(pos==-1)
41         pos=n-1;
42     for(int i=0;i<n;i++)
43         if(i!=pos)
44             printf("%c",s[i]);
45 return 0;
46 }
View Code

 

B.

当n是偶数的时候一定是每次都减2,也就是n/2.当n奇数的时候,就暴力减质数一直减到是偶数或者为0.注意要特判当前n是不是质数。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <set>
 6 #include <map>
 7 #include <vector>
 8 #include <queue>
 9 #include <cmath>
10 #include <cstdlib>
11 #include <stack>
12 
13 using namespace std;
14 const double eps = 1e-6;
15 const int MOD=1e9+7;
16 typedef long long LL;
17 typedef unsigned long long ull;
18 const int INF=2147000000;
19 const LL inf = 1e18;
20 LL gcd(LL a,LL b){
21     if(!b)return a;
22     return gcd(b,a%b);
23 }
24 LL lcm(LL a,LL b){
25     return a/gcd(a,b)*b;
26 }
27 const int maxn=2e5+100;
28 
29 int prime[maxn];
30 int vis[maxn];
31 int num;
32 int init(int n){
33     int m = (int)sqrt(n);
34     vis[1]=1;
35 
36     for(int i = 2;i<=m;i++){
37         for(int j =i*i; j<=n;j+=i){
38             vis[j]=1;
39         }
40     }
41     for(int i=2;i<=n;i++){
42         if(!vis[i]){
43             num++;
44             prime[num] = i;
45         }
46     }
47     return num;
48 }
49 bool judge(LL x){
50     int m =(int)sqrt(x);
51     for(int i=2;i<=m+1;i++){
52         if(x%i==0)
53             return false;
54     }
55     return true;
56 }
57 LL n;
58 int
59 main(){
60     cin>>n;
61     LL ans=0;
62     init(2e5);
63     if(n%2==0){
64         cout<<n/2<<endl;
65         return 0;
66     }
67     bool ok=1;
68     while(n%2){
69         if(judge(n)){
70             ans+=1;
71             ok=0;
72             break;
73         }
74 
75         int flag=0;
76         for(int i=1;i<=num&&prime[i]<=n;i++){
77             if(n%prime[i]==0){
78            // printf("!!%d\n",prime[i]);
79                 flag=prime[i];
80                 break;
81             }
82         }
83         //printf("%d\n",flag);
84         if(!flag)flag=n;
85         n-=flag;
86         ans++;
87     }
88     if(ok)
89     ans+=n/2;
90     cout<<ans<<endl;
91 return 0;
92 }
View Code

 

C.

这个题就是解一个一元二次方程,应该也可以三分来做。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <set>
 6 #include <map>
 7 #include <vector>
 8 #include <queue>
 9 #include <cmath>
10 #include <cstdlib>
11 #include <stack>
12 
13 using namespace std;
14 const double eps = 1e-6;
15 const int MOD=1e9+7;
16 typedef long long LL;
17 typedef unsigned long long ull;
18 const int INF=2147000000;
19 const LL inf = 1e18;
20 LL gcd(LL a,LL b){
21     if(!b)return a;
22     return gcd(b,a%b);
23 }
24 LL lcm(LL a,LL b){
25     return a/gcd(a,b)*b;
26 }
27 int main(){
28     int T;
29     scanf("%d",&T);
30 
31     int d;
32     for(int kas=1;kas<=T;kas++){
33         scanf("%d",&d);
34         double del = d*d - 4*d;
35         if(del<0){
36             printf("N\n");
37         }else if(del == 0){
38             double ans=(double)d/2;
39 
40             printf("Y %.9f %.9f\n",ans,(double)(d-ans));
41         }else{
42             double ans1 = (double)(d+sqrt(del))/2;
43             if(ans1<=d){
44                 printf("Y %.9f %.9f\n",ans1,(double)(d-ans1));
45             }else{
46                 double ans1 = (double)(d-sqrt(del))/2;
47                 if(ans1<0){
48                     printf("N\n");
49                 }else
50                     printf("Y %.9f %.9f\n",ans1,(double)(d-ans1));
51             }
52         }
53     }
54 return 0;
55 }
View Code

D.

最短路+贪心;我们先跑出最短路树来,如果k大于等于最短路树的边数,则树上的边全留下。否则的话就要删树上的边,删哪些呢?从最远(d[u]最大)的边开始删一定是最优的。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <set>
  6 #include <map>
  7 #include <vector>
  8 #include <queue>
  9 #include <cmath>
 10 #include <cstdlib>
 11 #include <stack>
 12 
 13 using namespace std;
 14 const double eps = 1e-6;
 15 const int MOD=1e9+7;
 16 typedef long long LL;
 17 typedef unsigned long long ull;
 18 const int INF=2147000000;
 19 const LL inf = 1e18;
 20 LL gcd(LL a,LL b){
 21     if(!b)return a;
 22     return gcd(b,a%b);
 23 }
 24 LL lcm(LL a,LL b){
 25     return a/gcd(a,b)*b;
 26 }
 27 const int maxn=3e5+100;
 28 int head[maxn],to[2*maxn],Next[2*maxn],w[2*maxn],id[2*maxn];
 29 struct Edge{
 30     int from,to,w,id;
 31 };
 32 vector<Edge>edges;
 33 int sz,n,m,k;
 34 void init(){
 35     sz=0;
 36     memset(head,-1,sizeof(head));
 37 }
 38 void add_edge(int a,int b,int c,int d){
 39     ++sz;
 40     to[sz]=b;
 41     w[sz]=c;
 42     id[sz]=d;
 43     Next[sz]=head[a];
 44     head[a]=sz;
 45 }
 46 struct HeapNode{
 47     int u;
 48     LL d;
 49     int from;
 50     bool operator <(const HeapNode& rhs)const{
 51         return d>rhs.d;
 52     }
 53 };
 54 int done[maxn],p[maxn];
 55 LL d[maxn];
 56 
 57 Edge edge[maxn];
 58 
 59 priority_queue<HeapNode>q;
 60 void dij(){
 61     q.push((HeapNode){1,0,-1});
 62     for(int i=0;i<=n;i++)
 63         d[i]=inf;
 64     while(!q.empty()){
 65         HeapNode x= q.top();q.pop();
 66         if(done[x.u])
 67             continue;
 68         done[x.u]=1;
 69         d[x.u] = x.d;
 70         p[x.u] = x.from;
 71         //printf("%d\n",x.from);
 72         for(int i=head[x.u];i!=-1;i=Next[i]){
 73             int v = to[i];
 74             if(d[v]>d[x.u]+w[i]){
 75                 q.push((HeapNode){v,d[x.u]+w[i],id[i]});
 76             }
 77         }
 78     }
 79 }
 80 
 81 struct Node{
 82     int u;
 83     LL d;
 84     int from;
 85     bool operator <(const Node &rhs)const{
 86         return d<rhs.d;
 87     }
 88 };
 89 int vis[maxn];
 90 
 91 priority_queue<Node>Q;
 92 
 93 int main(){
 94     scanf("%d%d%d",&n,&m,&k);
 95 
 96     init();
 97     for(int i=1;i<=m;i++){
 98         int a,b,c;
 99         scanf("%d%d%d",&a,&b,&c);
100         add_edge(a,b,c,i);
101         add_edge(b,a,c,i);
102         edge[i]=(Edge){a,b,c,i};
103     }
104     dij();
105     for(int i=1;i<=n;i++){
106         //printf("@%d\n",p[i]);
107         if(p[i]!=-1&& !vis[p[i]]){
108             edges.push_back(edge[p[i]]);
109             vis[p[i]]=1;
110             Q.push((Node){i,d[i],p[i]});
111            // printf("!!!%d %d %d %d\n",edge[p[i]].from,edge[p[i]].to,edge[p[i]].w,p[i]);
112         }
113     }
114     if(edges.size()<=k){
115         printf("%d\n",edges.size());
116         for(int i=0;i<edges.size();i++){
117             printf("%d ",edges[i].id);
118         }
119     }else{
120         int num = edges.size();
121         while(num>k&&!Q.empty()){
122             Q.pop();
123             num--;
124         }
125         printf("%d\n",k);
126         while(!Q.empty()){
127             printf("%d ",Q.top().from);
128             Q.pop();
129         }
130     }
131 return 0;
132 }
View Code

E.

树状数组或者线段树维护一下。因为每个点的值只可能是来自于它的祖先结点,所以跑dfs的时候,进入这个点的时候更新树状数组,退栈的时候还原树状数组

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <vector>
 6 
 7 using namespace std;
 8 const int maxn=3e5+100;
 9 typedef long long LL;
10 int head[maxn],to[2*maxn],Next[2*maxn];
11 int n,sz,m;
12 void add_edge(int a,int b){
13     sz++;
14     to[sz]=b;Next[sz]=head[a];head[a]=sz;
15 }
16 int lowbit(int x){
17     return x&(-x);
18 }
19 LL sumv[maxn];
20 void update(int x,int v){
21     while(x<=n){
22         sumv[x]+=v;
23         x+=lowbit(x);
24     }
25 }
26 LL query(int x){
27     LL res=0;
28     while(x){
29         res+=sumv[x];
30         x-=lowbit(x);
31     }
32     return res;
33 }
34 struct Node{
35     int d,x;
36 };
37 vector<Node>V[maxn];
38 int fa[maxn],dep[maxn];
39 LL ans[maxn];
40 
41 void dfs(int u,int Fa,int depth){
42     fa[u]=Fa;
43     dep[u]=depth;
44     for(int i=0;i<V[u].size();i++){
45         Node N = V[u][i];
46         update(min(N.d+depth,n),N.x);
47     }
48     ans[u] = query(n)-query(depth-1);
49     for(int i=head[u];i!=-1;i=Next[i]){
50         int v=to[i];
51         if(v==Fa)continue;
52         dfs(v,u,depth+1);
53     }
54     for(int i=0;i<V[u].size();i++){
55         Node N = V[u][i];
56         update(min(N.d+depth,n),-N.x);
57     }
58 }
59 
60 int main(){
61     scanf("%d",&n);
62     memset(head,-1,sizeof(head));
63     for(int i=1;i<n;i++){
64         int a,b;
65         scanf("%d%d",&a,&b);
66         add_edge(a,b);
67         add_edge(b,a);
68     }
69     scanf("%d",&m);
70     for(int i=1;i<=m;i++){
71         int v,d,x;
72         scanf("%d%d%d",&v,&d,&x);
73         V[v].push_back((Node){d,x});
74     }
75     dfs(1,-1,1);
76     for(int i=1;i<=n;i++){
77         printf("%I64d ",ans[i]);
78     }
79 return 0;
80 }
View Code

F.

贪心+分类讨论。

每一页多的为Max,少的为Min。那么一定是用少的将多的分隔开。所以如果大小关系不同则不会产生影响。否则的话,这一页我们要它最左边多出来的那块尽量长。lef=k-lastR;那么Max=Max-lef,Min=Min-1;然后我们分类讨论:

1.ceil(Max/k)-1>Min 则return false;

2.ceil(Max/k)<=Min

则说明右边不会剩下。则lastR=0。

3.ceil(Max/k)==Min-1的话,恰好被分割开,右边会有剩余,但是剩余的长度<=k,属于合法。
lastR= Max%k ==0?k:Max%k

这个也有叉点,要主要Min==Max的情况

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <cstdlib>
 7 
 8 using namespace std;
 9 const int maxn = 3e5 + 100;
10 int n, k;
11 int x[maxn][2];//0 x,1 y
12 int state,laststate,lastR;
13 int main(){
14     scanf("%d%d", &n, &k);
15     for(int i = 1; i <= n; i++){
16         scanf("%d", &x[i][0]);
17     }
18     for(int i = 1; i <= n; i++){
19         scanf("%d", &x[i][1]);
20     }
21     bool flag = 1;
22     for(int i = 1; i <= n; i++){ //x >= y state = 1;else state = 0;
23         int Min = min(x[i][0], x[i][1]);
24         int Max = max(x[i][0], x[i][1]);
25        // printf("%d %d\n",Min,Max);
26         if(x[i][0] > x[i][1])
27             state = 1;
28         else if(x[i][0] < x[i][1])
29             state = 0;
30         else state = -1;
31         if(state == laststate||laststate == -1||state == -1){
32             int lef = k - lastR;
33             Max = Max - lef;
34             Min = Min - 1;
35         }
36         //printf("%d %d\n",(int)ceil((double)Max/k),Min);
37 
38         if((int)ceil((double)Max/k)-1 > Min){
39             flag = 0;
40             break;
41         }else if((int)ceil((double)Max/k) <= Min){
42             lastR = 0;
43         }else{
44             lastR = Max%k == 0?k:Max%k;
45         }
46         laststate = state;
47     }
48     if(!flag){
49         printf("NO\n");
50     }else{
51         printf("YES\n");
52     }
53 return 0;
54 }
View Code

G.

好像是打反转标记的线段树,留坑

 

posted @ 2018-11-14 01:45  蒟蒻LQL  阅读(203)  评论(0编辑  收藏  举报