Codeforces Round #364 (Div. 2)

还是4个1a

记录代码

 

A

 1 //#define txtout
 2 //#define debug
 3 #include<bits/stdc++.h>
 4 #define mt(a,b) memset(a,b,sizeof(a))
 5 using namespace std;
 6 typedef long long LL;
 7 const double pi=acos(-1.0);
 8 const double eps=1e-8;
 9 const int inf=0x3f3f3f3f;
10 const int M=1e5+10;
11 int n,m;
12 int a[M];
13 bool v[M];
14 void solve(){
15 
16 }
17 int main(){
18     #ifdef txtout
19     freopen("in.txt","r",stdin);
20     freopen("out.txt","w",stdout);
21     #endif // txtout
22     while(~scanf("%d",&n)){
23         int sum=0;
24         for(int i=1;i<=n;i++){
25             scanf("%d",&a[i]);
26             sum+=a[i];
27             v[i]=false;
28         }
29         int avg=sum*2/n;
30         for(int i=1;i<=n;i++){
31             bool flag=false;
32             for(int j=1;j<=n;j++){
33                 if(v[j]) continue;
34                 for(int k=j+1;k<=n;k++){
35                     if(v[k]) continue;
36                     if(a[j]+a[k]==avg){
37                         flag=true;
38                         printf("%d %d\n",j,k);
39                         v[j]=true;
40                         v[k]=true;
41                         break;
42                     }
43                 }
44                 if(flag) break;
45             }
46         }
47     }
48     return 0;
49 }
View Code

 

 

B

 1 //#define txtout
 2 //#define debug
 3 #include<bits/stdc++.h>
 4 #define mt(a,b) memset(a,b,sizeof(a))
 5 using namespace std;
 6 typedef long long LL;
 7 const double pi=acos(-1.0);
 8 const double eps=1e-8;
 9 const int inf=0x3f3f3f3f;
10 const int M=1e5+10;
11 int n,m;
12 set<int> sx,sy;
13 int main(){
14     #ifdef txtout
15     freopen("in.txt","r",stdin);
16     freopen("out.txt","w",stdout);
17     #endif // txtout
18     while(~scanf("%d%d",&n,&m)){
19         sx.clear();
20         sy.clear();
21         LL tn=n;
22         bool flag=false;
23         int x,y;
24         while(m--){
25             scanf("%d%d",&x,&y);
26             sx.insert(x);
27             sy.insert(y);
28             LL sum=0;
29             x=sx.size();
30             y=sy.size();
31             sum=tn*tn-tn*x-tn*y+1LL*x*y;
32             if(flag) putchar(' ');
33             printf("%I64d",sum);
34             flag=true;
35         }
36         puts("");
37     }
38     return 0;
39 }
View Code

 

 

C  

题意  给一个串,问选一个最短的子串 ,使得子串中有原串所有类型的字符

 

比赛是用二分,  枚举起点,二分终点 ,通过前n项和 O56判出是否满足

 

 1 //#define txtout
 2 //#define debug
 3 #include<bits/stdc++.h>
 4 #define mt(a,b) memset(a,b,sizeof(a))
 5 using namespace std;
 6 typedef long long LL;
 7 const double pi=acos(-1.0);
 8 const double eps=1e-8;
 9 const int inf=0x3f3f3f3f;
10 const int M=1e5+10;
11 int n;
12 char a[M];
13 int sum[64][M];
14 int toid(char c){
15     if(c>='a'&&c<='z') return c-'a';
16     return c-'A'+26;
17 }
18 void init(){
19     for(int i=0;i<52;i++){
20         sum[i][0]=0;
21     }
22     sum[toid(a[0])][0]=1;
23     for(int i=1;i<n;i++){
24         for(int j=0;j<52;j++){
25             sum[j][i]=sum[j][i-1];
26         }
27         sum[toid(a[i])][i]++;
28     }
29 }
30 bool judge(int s,int mid){
31     for(int i=0;i<52;i++){
32         if(sum[i][n-1]==0) continue;
33         int total=sum[i][mid];
34         if(s>0) total-=sum[i][s-1];
35         if(total<=0) return false;
36     }
37     return true;
38 }
39 int bs(int s){
40     int L=s,R=n-1,result=-1;
41     while(L<=R){
42         int mid=(L+R)>>1;
43         if(judge(s,mid)){
44             result=mid;
45             R=mid-1;
46         }
47         else{
48             L=mid+1;
49         }
50     }
51     return result;
52 }
53 int solve(){
54     init();
55     int answer=n;
56     for(int i=0;i<n;i++){
57         int last=bs(i);
58         if(last==-1) break;
59         answer=min(answer,last-i+1);
60     }
61     return answer;
62 }
63 int main(){
64     #ifdef txtout
65     freopen("in.txt","r",stdin);
66     freopen("out.txt","w",stdout);
67     #endif // txtout
68     while(~scanf("%d%s",&n,a)){
69         printf("%d\n",solve());
70     }
71     return 0;
72 }
View Code

 赛后考虑单调队列, 双指针实现,比上述方法快10倍,  开始 起点和终点都在 0,  如果当前种类少于总的种类,则序列一定要变长,  终点往后走一个.  

如果当前种类等于总共的种类, 更新答案.  此时说明该起点的最近的终点已经找到,  起点往后走一个.  那么下一个起点必定少了一个字符,  因此种类数只会比之前差,或相等, 因此终点只可能往后走,或是停留原位,不可能往前走,

那么最终起点和终点都是on的往后走, 复杂度on.

 

 1 //#define txtout
 2 //#define debug
 3 #include<bits/stdc++.h>
 4 #define mt(a,b) memset(a,b,sizeof(a))
 5 using namespace std;
 6 typedef long long LL;
 7 const double pi=acos(-1.0);
 8 const double eps=1e-8;
 9 const int inf=0x3f3f3f3f;
10 const int M=1e5+10;
11 int n;
12 char a[M];
13 int sum[64];
14 int toint(char c){
15     if(c>='a'&&c<='z') return c-'a';
16     return c-'A'+26;
17 }
18 int solve(){
19     mt(sum,0);
20     int total=0;
21     for(int i=0;i<n;i++){
22         int id=toint(a[i]);
23         sum[id]++;
24         if(sum[id]==1) total++;
25     }
26     int result=n;
27     mt(sum,0);
28     int s=0,t=0,nowTotal=1;
29     sum[toint(a[0])]++;
30     while(true){
31         if(s>=n) break;
32         if(total==nowTotal){
33             result=min(result,t-s+1);
34             int id=toint(a[s]);
35             sum[id]--;
36             if(sum[id]==0) nowTotal--;
37             if(s+1<=t){
38                 s++;
39                 continue;
40             }
41             s=t+1;
42             t=s;
43             continue;
44         }
45         if(t+1>=n) break;
46         t++;
47         int id=toint(a[t]);
48         sum[id]++;
49         if(sum[id]==1) nowTotal++;
50     }
51     return result;
52 }
53 int main(){
54     #ifdef txtout
55     freopen("in.txt","r",stdin);
56     freopen("out.txt","w",stdout);
57     #endif // txtout
58     while(~scanf("%d%s",&n,a)){
59         printf("%d\n",solve());
60     }
61     return 0;
62 }
View Code

 

 

D

 1 //#define txtout
 2 //#define debug
 3 #include<bits/stdc++.h>
 4 #define mt(a,b) memset(a,b,sizeof(a))
 5 using namespace std;
 6 typedef long long LL;
 7 const double pi=acos(-1.0);
 8 const double eps=1e-8;
 9 const int inf=0x3f3f3f3f;
10 const int M=1e5+10;
11 int n,l,v1,v2,k;
12 
13 bool judge(double cut_time,double len,int m){
14     #ifdef debug
15     printf("cut_time=%.3f   len=%.3f   m=%d\n",cut_time,len,m);
16     #endif // debug
17     if(m==0) return true;
18 //    if(len<eps) return true;
19     if(v2*cut_time<len) return false;
20     double t1=(len-v2*cut_time)/(v1-v2);
21     double t2=cut_time-t1;
22     double left=len-v1*t2;
23     #ifdef debug
24     printf("t1 = %.3f   t2 = %.3f    left = %.3f\n",t1,t2,left);
25     #endif // debug
26     if(left<eps) return true;
27     double carleft=len-v2*t2;
28     double meettime=(left-carleft)/(v1+v2);
29     left-=v1*meettime;
30     if(left<eps) return true;
31     return judge(t1-meettime,left,m-1);
32 }
33 double solve(){
34     int m=n/k;
35     if(n%k) m++;
36     double L=0,R=l*1.0/v1;
37     double answer=R;
38     int step=100;
39     while(step--){
40         double mid=(L+R)*0.5;
41         #ifdef debug
42         printf("judge\n");
43         #endif // debug
44         if(judge(mid,l,m)){
45             answer=mid;
46             R=mid;
47         }
48         else{
49             L=mid;
50         }
51     }
52     return answer;
53 }
54 int main(){
55     #ifdef txtout
56     freopen("in.txt","r",stdin);
57     freopen("out.txt","w",stdout);
58     #endif // txtout
59     while(~scanf("%d%d%d%d%d",&n,&l,&v1,&v2,&k)){
60         printf("%.10f\n",solve());
61     }
62     return 0;
63 }
View Code

 

 

E  赛后过的,记录一下,其实不难。题意给一个树,其中有2*m个节点是学校。现在要把这些学校两两一组配对,每一对有距离,目标使得m个距离的和最大。

解法:宏观的来看。遍历每一条边,它能经过的次数是左右两边学校个数的小值。 通过dfs处理以u为根的子树的学校个数。 基于贪心的理论,即一条边左右两边都有点的话,会尽可能的让他们配对,那么配对数就是min(left,right)。也就是不考虑具体是哪两个匹配到一起,只要左右两边有点,就会尽可能的去匹配。

 

 1 //#define debug
 2 
 3 #include<bits/stdc++.h>
 4 using namespace std;
 5 typedef long long LL;
 6 const int M=2e5+10;
 7 struct E{
 8     int u,v;
 9 }e[M];
10 vector<int> g[M];
11 int x[M];
12 int sum[M];
13 bool is[M];
14 int n,m;
15 void init(){
16     for(int i=1;i<=n;i++){
17         is[i]=false;
18         g[i].clear();
19     }
20     for(int i=0;i<m;i++){
21         is[x[i]]=true;
22     }
23     for(int i=0;i<n-1;i++){
24         g[e[i].u].push_back(e[i].v);
25         g[e[i].v].push_back(e[i].u);
26     }
27 }
28 void dfs_sum(int u,int fa){
29     sum[u]=is[u];
30     for(int i=0;i<g[u].size();i++){
31         int v=g[u][i];
32         if(v==fa) continue;
33         dfs_sum(v,u);
34         sum[u]+=sum[v];
35     }
36 }
37 LL answer;
38 void dfs(int u,int fa){
39     for(int i=0;i<g[u].size();i++){
40         int v=g[u][i];
41         if(v==fa) continue;
42         int son=sum[v];
43         int other=m-sum[v];
44         if(son<=other){
45             answer+=son;
46         }
47         else{
48             answer+=other;
49         }
50         dfs(v,u);
51     }
52 }
53 LL solve(){
54     init();
55     dfs_sum(1,-1);
56 
57     #ifdef debug
58     for(int i=1;i<=n;i++){
59         printf("%d ",sum[i]);
60     }
61     puts("");
62     #endif
63 
64     answer=0;
65     dfs(1,-1);
66     return answer;
67 }
68 int main(){
69     while(~scanf("%d%d",&n,&m)){
70         m<<=1;
71         for(int i=0;i<m;i++){
72             scanf("%d",&x[i]);
73         }
74         for(int i=0;i<n-1;i++){
75             scanf("%d%d",&e[i].u,&e[i].v);
76         }
77         printf("%I64d\n",solve());
78     }
79     return 0;
80 }
View Code

 

 

F 赛后研究好几天也没过,后看了别人的思想 ,实现了好几天,终于过了.  题意给一个无向图, 删去小于等于2条边,使得st两点不连通 ,删去边 有花费 ,问总花费最小的方案.

解法:  本来不通 0.   随便找一条 S 到T 路径,  必须删去路径上的一条边, 枚举 删去哪条 ,因为路径的边数只有n-1条.  删去边后,  判断, 如果不通了 ,  那么删这条边是一种方案,  如果还通,  做tarjan缩点, 

当ST在一个连通分量内, 因为我们只剩一条可以删, 因此肯定无解 ,   不在一个连通分量时 ,  我们还是随便找一条 S到T的路径, 判断 路径上是否有桥, 有则可以通过删他达到目的.

枚举第一条边n ,  tarjan m,  n*m的复杂度,  可能有更快的方法?

 

  1 //#define txtout
  2 //#define debug
  3 #include<bits/stdc++.h>
  4 #define mt(a,b) memset(a,b,sizeof(a))
  5 using namespace std;
  6 typedef long long LL;
  7 const double pi=acos(-1.0);
  8 const double eps=1e-8;
  9 const int inf=0x3f3f3f3f;
 10 const int M=1e5+10;
 11 int n,m,s,t;
 12 struct E {
 13     int u,v,w;
 14 } e[M];
 15 struct G {
 16     struct E {
 17         int v,w,id,next;
 18     } e[M];
 19     int le,head[M];
 20     void init(int n) {
 21         le=0;
 22         for(int i=0; i<=n; i++) head[i]=-1;
 23     }
 24     void add(int u,int v,int w,int id) {
 25         e[le].v=v;
 26         e[le].w=w;
 27         e[le].id=id;
 28         e[le].next=head[u];
 29         head[u]=le++;
 30     }
 31 } g;
 32 struct A {
 33     int sum;
 34     vector<int> id;
 35     void init() {
 36         sum=-1;
 37         id.clear();
 38     }
 39     void update(int tsum,int id1,int id2) {
 40         if(sum==-1||tsum<sum) {
 41             sum=tsum;
 42             id.clear();
 43             if(~id1) id.push_back(id1);
 44             if(~id2) id.push_back(id2);
 45         }
 46     }
 47 } answer;
 48 class Tarjan_U { ///����ͼ��ͨ�������� O(V+E)
 49     typedef int typec; ///��Ȩ������
 50     static const int ME=1e5+10; ///�ߵĸ���
 51     static const int MV=1e3+10; ///��ĸ���
 52     int n,Bcnt,Index,num[MV],dfn[MV],low[MV],belong[MV];
 53     stack<int> s;
 54     void addqiao(int u,int v,typec w) {
 55         now.u=u;
 56         now.v=v;
 57         now.w=w;
 58         qiao.push_back(now);
 59     }
 60     void tarjan(int u) {
 61         s.push(u);
 62         dfn[u]=low[u]=++Index;
 63         int v;
 64         for(int i=g.head[u]; ~i; i=g.e[i].next) {
 65             if(g.e[i].vis) continue;
 66             g.e[i].vis=g.e[i^1].vis=true;
 67             v=g.e[i].v;
 68             if (!dfn[v]) {
 69                 tarjan(v);
 70                 low[u]=min(low[u],low[v]);
 71                 if(dfn[u]<low[v]){
 72                     addqiao(u,v,g.e[i].w);
 73                     isbridge[g.e[i].id]=true;
 74                 }
 75                 continue;
 76             }
 77             low[u]=min(low[u],dfn[v]);
 78         }
 79         if(dfn[u]!=low[u]) return ;
 80         Bcnt++;
 81         do {
 82             v=s.top();
 83             s.pop();
 84             belong[v]=Bcnt;
 85             num[Bcnt]++;
 86         } while(v!=u);
 87     }
 88     struct G {
 89         struct E {
 90             int id;
 91             int v,next;
 92             bool vis;
 93             typec w;
 94         } e[ME];
 95         int le,head[MV];
 96         void init(int n) {
 97             le=0;
 98             for(int i=0; i<=n; i++) head[i]=-1;
 99         }
100         void add(int u,int v,typec w,int id) {
101             e[le].vis=false;
102             e[le].v=v;
103             e[le].w=w;
104             e[le].id=id;
105             e[le].next=head[u];
106             head[u]=le++;
107         }
108     } g;
109     struct Q {
110         int u,v;
111         typec w;
112     } now;
113     vector<Q> qiao;
114     bool isbridge[ME];
115 public:
116     bool is_bridge(int id){
117         return isbridge[id];
118     }
119     void init(int tn) { ///������������±� 1 ��ʼ
120         n=tn;
121         g.init(n);
122     }
123     void add(int u,int v,typec w,int id) {
124         g.add(u,v,w,id);
125         g.add(v,u,w,id);
126     }
127     void solve() {
128         Index=Bcnt=0;
129         for(int i=1; i<=n; i++) {
130             num[i]=dfn[i]=low[i]=0;
131         }
132         for(int i=0;i<m;i++){
133 
134             isbridge[i]=false;
135         }
136         qiao.clear();
137         while(!s.empty()) s.pop();
138         for(int i=1; i<=n; i++) {
139             if(!dfn[i]) {
140                 tarjan(i);
141             }
142         }
143     }
144     int getbcnt() { ///��ͨ�����ĸ���
145         return Bcnt;
146     }
147     int getbelong(int id) { ///�����ĸ������������±� 1 ��ʼ
148         return belong[id];
149     }
150     int getnum(int id) { ///ij�������ĵ�ĸ���
151         return num[id];
152     }
153 } tarjan;
154 bool tabu[M];
155 int pre[M];
156 vector<int> EID,EID2;
157 bool dfs(int u,int deleteID) {
158     tabu[u]=true;
159     if(u==t) return true;
160     for(int i=g.head[u]; ~i; i=g.e[i].next) {
161         int id=g.e[i].id;
162         if(id==deleteID) continue;
163         int v=g.e[i].v;
164         if(tabu[v]) continue;
165         pre[v]=u;
166         bool flag=dfs(v,deleteID);
167         if(flag) return true;
168     }
169     return false;
170 }
171 bool check_c(int deleteID) {
172     for(int i=1; i<=n; i++) {
173         tabu[i]=false;
174     }
175     return dfs(s,deleteID);
176 }
177 void get_edge(vector<int> &a,int deleteID) {
178     a.clear();
179     int u=t;
180     while(u!=s) {
181         for(int i=g.head[u]; ~i; i=g.e[i].next) {
182             int id=g.e[i].id;
183             if(id==deleteID) continue;
184             int v=g.e[i].v;
185             if(v!=pre[u]) continue;
186             a.push_back(g.e[i].id);
187             u=v;
188             break;
189         }
190     }
191 }
192 void Delete(int deleteID) {
193     bool flag=check_c(deleteID);
194     if(!flag) {
195         answer.update(e[deleteID].w,deleteID,-1);
196         return ;
197     }
198     tarjan.init(n);
199     for(int i=0;i<m;i++){
200         if(i==deleteID) continue;
201         tarjan.add(e[i].u,e[i].v,e[i].w,i);
202     }
203     tarjan.solve();
204     if(tarjan.getbelong(s)==tarjan.getbelong(t)) return ;
205     get_edge(EID2,deleteID);
206     for(int i=0;i<EID2.size();i++){
207         int id=EID2[i];
208         #ifdef debug
209         printf("id2=%d\n",id);
210         #endif // debug
211         if(!tarjan.is_bridge(id)) continue;
212         answer.update(e[deleteID].w+e[id].w,deleteID,id);
213     }
214 }
215 void solve() {
216     answer.init();
217     g.init(n);
218     for(int i=0; i<m; i++) {
219         g.add(e[i].u,e[i].v,e[i].w,i);
220         g.add(e[i].v,e[i].u,e[i].w,i);
221     }
222     bool flag=check_c(-1);
223     if(!flag) {
224         answer.update(0,-1,-1);
225         return ;
226     }
227     get_edge(EID,-1);
228     for(int i=0; i<EID.size(); i++) {
229         #ifdef debug
230         printf("id=%d\n",EID[i]);
231         #endif // debug
232         Delete(EID[i]);
233     }
234 }
235 int main() {
236 #ifdef txtout
237     freopen("in.txt","r",stdin);
238     freopen("out.txt","w",stdout);
239 #endif // txtout
240     while(~scanf("%d%d%d%d",&n,&m,&s,&t)) {
241         for(int i=0; i<m; i++) {
242             scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
243         }
244         solve();
245         int sum=answer.sum;
246         printf("%d\n",sum);
247         if(sum==-1) continue;
248         printf("%d\n",answer.id.size());
249         for(int i=0; i<answer.id.size(); i++) {
250             printf("%d%c",answer.id[i]+1,i==answer.id.size()-1?'\n':' ');
251         }
252     }
253     return 0;
254 }
View Code

 

 

 

 

 

end

posted on 2016-07-23 10:42  gaolzzxin  阅读(162)  评论(0编辑  收藏  举报