2015-2016 Northwestern European Regional Contest (NWERC 2015)

题目链接  Codeforces_Gym_101485

Problem A

直接用优先队列进行贪心即可

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<cmath>
 7 #include<string>
 8 #include<set>
 9 #include<queue>
10 #include<map>
11 using namespace std;
12 const int inf=(1<<30)-1;
13 const int maxn=300010;
14 #define REP(i,n) for(int i=(0);i<(n);i++)
15 #define FOR(i,j,n) for(int i=(j);i<=(n);i++)
16 #define Rep(x) for(int i=head[x],y;~i;i=e[i].next) if(!vis[y=e[i].to])
17 typedef long long ll;
18 typedef pair<int,int> PII;
19 int IN(){
20     int c,f,x;
21     while (!isdigit(c=getchar())&&c!='-');c=='-'?(f=1,x=0):(f=0,x=c-'0');
22     while (isdigit(c=getchar())) x=(x<<1)+(x<<3)+c-'0';return !f?x:-x;
23 }
24 #define de(x) cout << #x << "=" << x << endl
25 #define MP make_pair
26 #define PB push_back
27 #define fi first
28 #define se second
29 int n,m,T;
30 struct data{
31     int l,r;
32 }a[maxn];
33 bool cmp(data a,data b)
34 {
35     return a.l<b.l;
36 }
37 priority_queue<int,vector<int>,greater<int> >  Q;
38 int main()
39 {
40     while(~scanf("%d%d",&n,&m))
41     {
42         FOR(i,1,n) {
43             a[i].l=IN();
44             a[i].r=IN();
45             a[i].r+=a[i].l;
46         }
47         sort(a+1,a+n+1,cmp);
48         Q.push(a[1].r+m);
49         int ans=0;
50         for(int i=2;i<=n;i++)
51         {
52             while(!Q.empty()&&Q.top()<a[i].l) Q.pop();
53             int u=Q.top();
54             if(u-m<=a[i].l&&a[i].l<=u) ans++,Q.pop();
55             Q.push(a[i].r+m);
56         }
57         printf("%d\n",ans);
58         while(!Q.empty()) Q.pop();
59     }
60     return 0;
61 }
View Code

 

Problem B

比赛时居然现场没人开这道题

其实就是一个简单的dp

先要把所有包含的全部删除

f[i][j]代表前i个人分成j组的最大值

f[i][j] = max(f[i][j], f[k- 1][j - 1] + h[k].b - h[k].a)

排序后枚举k进行简单的转移即可

最后统计一下答案

——hnqw1214

……其实也不简单

这道题关键就是要想到把些时间段包含别人的人全部扔出来,放到另外一个地方。

去重蛮难想的,QW写的。

最后还要和之前的状态混合枚举一下。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define rep(i, a, b)    for (int i(a); i <= (b); ++i)
 6 #define dec(i, a, b)    for (int i(a); i >= (b); --i)
 7 #define fi        first
 8 #define    se        second
 9 
10 struct ss
11 {
12     int a,b;
13 };
14 ss g[210], h[210];
15 ss d[210];
16 int n,p;
17 bool contain(ss a,ss b){
18     return a.a<=b.a&&a.b>=b.b;
19 }
20 
21 bool b[1010];
22 
23 int f[203][203];
24 int ans = 0;
25 int et = 0;
26 
27 bool cmp(const ss &a, const ss &b){
28     return a.b - a.a > b.b - b.a;
29 }
30 
31 bool cmp1(const ss &a, const ss &b){
32     return a.a < b.a;
33 }
34 
35 int main()
36 {
37 
38     scanf("%d%d",&n,&p);
39     int i,j;
40     for (i=1;i<=n;i++)
41         scanf("%d%d",&g[i].a,&g[i].b);
42     int cnt=0;
43     for (i=1;i<n;i++)
44         for (j=i+1;j<=n;j++)
45         {
46             if (contain(g[i],g[j]))
47                 b[i]=true;
48             else if (contain(g[j],g[i]))
49                 b[j]=true;
50         }
51 
52 
53     for (i=1;i<=n;i++) if (!b[i]) h[++cnt]=g[i];
54 
55     sort(h + 1, h + cnt + 1, cmp1);
56 
57     
58 //    printf("%d\n", cnt);
59 //    rep(i, 1, cnt) printf("%d %d\n", h[i].a, h[i].b);
60     
61     rep(i, 1, n) if (b[i]) d[++et] = g[i];
62 
63     sort(d + 1, d + et + 1, cmp);
64 
65     rep(i, 0, cnt) rep(j, 0, p) f[i][j] = -(1e9 + 10000);
66     f[0][0] = 0;
67     rep(k, 1, p){  
68         rep(i, 1, cnt){  
69             rep(j, 1, i){  
70                 if (h[j].b - h[i].a <= 0) continue;  
71                 f[i][k] = max(f[i][k], f[j - 1][k - 1] + h[j].b - h[i].a);  
72             }  
73         }  
74     }
75 
76 
77 //    ans = f[cnt][p];
78     int ff = 0;
79     rep(i, 0, p){
80         ff = ff + d[i].b - d[i].a;
81         if (p >= i) ans = max(ans, ff + f[cnt][p - i]);
82     }
83         
84     printf("%d\n", ans);    
85 
86     
87 
88 }
View Code

 

Problem C

首先预处理一下哪些线段是相交的

然后把每条线段看成一个点

如果线段相交就连一条边

判断一下这张图是否是二分图

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstdlib>
  5 #include<algorithm>
  6 #include<cstring>
  7 #include<string>
  8 #include<vector>
  9 #include<map>
 10 #include<set>
 11 #include<queue>
 12 
 13 using namespace std;
 14 
 15 #define rep(i, a, b)    for (int i(a); i <= (b); ++i)
 16 #define dec(i, a, b)    for (int i(a); i >= (b); --i)
 17 #define fi        first
 18 #define    se        second
 19 
 20 typedef long long LL;
 21 
 22 const double eps = 1e-8;
 23 
 24 double sgn(double x){
 25     if (fabs(x) < eps)return 0;
 26     if(x < 0)return -1;
 27     else return 1;
 28 }
 29 
 30 struct point
 31 {
 32     double x,y;
 33     point(){}
 34     point(double _x,double _y):x(_x),y(_y)
 35     {}
 36     point operator -(const point &b) const
 37     {
 38         return point(x-b.x,y-b.y);
 39     }
 40     double operator *(const point &b) const
 41     {
 42         return x*b.x+y*b.y;
 43     }
 44     double operator ^(const point &b) const
 45     {
 46         return x*b.y-y*b.x;
 47     }
 48 };
 49 struct line
 50 {
 51     point s,e;
 52     double a,b,c;
 53     line()
 54     {
 55         
 56     }
 57     line (point _s,point _e):s(_s),e(_e)
 58     {
 59         a=e.y-s.y;
 60         b=s.x-e.x;
 61         c=e.x*s.y-s.x*e.y;
 62     }
 63 };
 64 double cross(point sp,point ep,point op)
 65 {
 66     return (sp.x-op.x)*(ep.y-op.y)-(sp.y-op.y)*(ep.x-op.x);
 67 }
 68 bool samepoint(point p1,point p2)
 69 {
 70     if (fabs(p1.x-p2.x)>eps) return false;
 71     if (fabs(p1.y-p2.y)>eps) return false;
 72     return true;
 73 }
 74 bool inter(line l1,line l2)
 75 {
 76     return
 77     max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
 78     max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
 79     max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
 80     max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
 81     sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s)) <= 0 &&
 82     sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s)) <= 0;
 83 }
 84 point intersection(line u,line v)
 85 {
 86     point p;
 87     p.x=(cross(v.e,u.e,u.s)*v.s.x-cross(v.s,u.e,u.s)*v.e.x)/(cross(v.e,u.e,u.s)-cross(v.s,u.e,u.s));
 88     p.y=(cross(v.e,u.e,u.s)*v.s.y-cross(v.s,u.e,u.s)*v.e.y)/(cross(v.e,u.e,u.s)-cross(v.s,u.e,u.s));
 89     return p;
 90 }
 91 point interpoint(line l1, line l2)
 92 {
 93     point tmp;
 94     if(fabs(l1.b)<eps)
 95     {
 96         tmp.x=-l1.c/l1.a;
 97         tmp.y=(-l2.c-l2.a*tmp.x)/l2.b;
 98     }
 99     else
100     {
101         tmp.x=(l1.c*l2.b-l1.b*l2.c)/(l1.b*l2.a-l2.b*l1.a);
102         tmp.y=(-l1.c-l1.a*tmp.x)/l1.b;
103     }
104     return tmp;
105 }
106 int w,p,cnt;
107 point well[1010];
108 line pipe[1010];
109 int f[1010][1010];
110 pair<int,int> g[1000010];
111 int can[1010];
112 int used[1010];
113 
114 vector <int> e[1010];
115 vector <int> v[1010];
116 
117 
118 
119 void dfs(int x, int now){
120     //    printf("%d %d\n", x, now);
121     if (now == cnt){
122         puts("possible");
123         exit(0);
124     }
125     
126     if (x > p) return ;
127     
128     dfs(x + 1, now);
129     
130     
131     
132     if (can[x] == 0){
133         for (auto u : e[x]){
134             can[u] = 1;
135         }
136         
137         vector <int> ct;
138         
139         for (auto u : v[x]){
140             if (!used[u]){
141                 ct.push_back(u);
142                 used[u] = 1;
143             }
144         }
145         
146         dfs(x + 1, now + (int)ct.size());
147         
148         for (auto u : ct) used[u] = 0;
149     }
150 }
151 int vis[100010];
152 int main(){
153     
154     
155     
156     scanf("%d%d",&w,&p);
157     
158     int i,j;
159     for (i=1;i<=w;i++)
160         scanf("%lf%lf",&well[i].x,&well[i].y);
161     for (i=1;i<=p;i++)
162     {
163         point po;
164         int id;
165         scanf("%d%lf%lf",&id,&po.x,&po.y);
166         pipe[i]=line(well[id],po);
167     }
168     //    printf("%d %d\n", w, p);
169     cnt=0;
170     for (i=1;i<p;i++){
171         for (j=i+1;j<=p;j++){
172             if (inter(pipe[i],pipe[j])&&!samepoint(pipe[i].s,interpoint(pipe[i],pipe[j]))||samepoint(pipe[i].e,pipe[j].e)){
173                 cnt++;
174                 f[i][j]=cnt;
175                 g[cnt].first=i;
176                 g[cnt].second=j;
177             }
178         }
179     }
180     /*
181      rep(i, 1, p){
182      rep(j, 1, p) printf("%d ", f[i][j]);
183      putchar(10);
184      }
185      */
186     rep(i, 1, p) rep(j, 1, p) if (i > j) f[i][j] = f[j][i];
187     
188     rep(i, 1, p){
189         rep(j, 1, p) if (f[i][j] > 0) v[i].push_back(f[i][j]), e[i].push_back(j);
190     }
191     /*
192      rep(i, 1, p){
193      for (auto u : v[i]) printf("%d ", u);
194      putchar(10);
195      }
196      */
197     //dfs(1, 0);
198     queue<int> Q;
199     rep(i,1,p) {
200         if(vis[i]) continue;
201         Q.push(i);vis[i]=1;
202         while(!Q.empty()) {
203             int u=Q.front();Q.pop();
204             for(auto x:e[u]) {
205                 if(vis[x]==vis[u]) return puts("impossible"),0;
206                 else if(!vis[x]) vis[x]=(vis[u]==1)?2:1,Q.push(x);
207             }
208         }
209     }    
210     puts("possible");
211     
212     return 0;    
213     
214 }
View Code

 

Problem D

根据题意进行记忆化搜索

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define rep(i, a, b)    for (int i(a); i <= (b); ++i)
 6 #define dec(i, a, b)    for (int i(a); i >= (b); --i)
 7 
 8 typedef long long LL;
 9 
10 const int N = 1e6 + 10;
11 
12 LL n, r, p;
13 LL f[N];
14 
15 LL dp(LL n){
16     if (n <= 1) return 0;
17     if (~f[n]) return f[n];
18     LL ret = 6e18;
19     for (LL i = 2;i <= n; i++) ret = min(ret, dp((n - 1) / i + 1) + (i - 1) * p + r);
20     return f[n] = ret;
21 }
22 
23 int main(){
24 
25     scanf("%lld%lld%lld", &n, &r, &p);
26     memset(f, -1, sizeof f);
27     printf("%lld\n", dp(n));
28     return 0;
29 }
View Code

 

Problem E

构造二分图

把所有的算式看成一个点集

所有的答案看成一个点集

如果算式可以得到该答案就连边

然后求二分图的最大匹配

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 struct ss
 5 {
 6     ll x,y;
 7 } a[2510];
 8 unordered_map<ll,ll> mat,used;
 9 ll result[2521],fuhao[2521],n;
10 bool crosspath(int k)
11 {
12     ll j=a[k].x+a[k].y;
13     if (!used[j])
14     {
15         used[j]=1;
16         if (mat[j]==0||crosspath(mat[j]))
17         {
18             mat[j]=k;
19             result[k]=j;
20             fuhao[k]=0;
21             return true;
22         }
23     }
24     j=a[k].x-a[k].y;
25     if (!used[j])
26     {
27         used[j]=1;
28         if (mat[j]==0||crosspath(mat[j]))
29         {
30             mat[j]=k;
31             result[k]=j;
32             fuhao[k]=1;
33             return true;
34         }
35     }
36     j=a[k].x*a[k].y;
37     if (!used[j])
38     {
39         used[j]=1;
40         if (mat[j]==0||crosspath(mat[j]))
41         {
42             mat[j]=k;
43             result[k]=j;
44             fuhao[k]=2;
45             return true;
46         }
47     }
48     return false;
49 }
50 int main()
51 {
52     scanf("%lld",&n);
53     int i;
54     for (i=1;i<=n;i++)
55         scanf("%lld%lld",&a[i].x,&a[i].y);
56     int match=0;
57     for (i=1;i<=n;i++)
58     {
59         if (crosspath(i))
60             match++;
61         used.clear();
62     }
63     if (match<n)
64         puts("impossible");
65     else
66     {
67         for (i=1;i<=n;i++)
68         {
69             printf("%lld ",a[i].x);
70             if (fuhao[i]==0) printf("+ ");
71             else if (fuhao[i]==1) printf("- ");
72             else printf("* ");
73             printf("%lld ",a[i].y);
74             printf("= ");
75             printf("%lld\n",result[i]);
76         }
77     }
78     return 0;
79 }
View Code

 

Problem F

Problem G

其实就是一个三维偏序问题

用cdq分治求解即可

(模板题哦)

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 #define rep(i, a, b)    for (int i(a); i <= (b); ++i)
  6 #define dec(i, a, b)    for (int i(a); i >= (b); --i)
  7 
  8 typedef long long LL;
  9 
 10 const int N = 1e6 + 10;
 11 
 12 struct Node
 13 { 
 14     int x, y, z, f, cnt; 
 15     void read() {  f = 0; }
 16     bool operator < (const Node &rhs) const
 17     {
 18         if (x != rhs.x) return x < rhs.x;
 19         if (y != rhs.y) return y < rhs.y;
 20         return z < rhs.z;
 21     }
 22     bool operator == (const Node &rhs) const
 23     { return x == rhs.x && y == rhs.y && z == rhs.z; }
 24 }
 25 
 26 a[N], b[N];
 27 
 28 
 29 int n, st[N<<1], ans[N];
 30 
 31 void init(){
 32     sort(a + 1, a + n + 1);
 33     int sz = 0;
 34     for (int i = 1; i <= n; ++i)
 35     {
 36         b[++sz] = a[i]; b[sz].cnt = 1; int j = i;
 37         while (j < n && a[j + 1] == a[j]) { ++j; b[sz].cnt++;}
 38         i = j;
 39     }
 40     n = sz;
 41     memset(st, 0, sizeof st);
 42 }
 43 
 44 void add(int k, int num){
 45     while (k <= n)
 46     {
 47         st[k] += num;
 48         k += k & (-k);
 49     }
 50 }
 51 int query(int k){
 52     int ans = 0;
 53     while (k){
 54         ans += st[k];
 55         k -= k & (-k);
 56     }
 57     return ans;
 58 }
 59 
 60 void cdq(int l, int r){
 61     if (l == r) return;
 62     int mid = l + r >> 1;
 63     cdq(l, mid);
 64     cdq(mid + 1, r);
 65     int i = l, j = mid + 1;
 66     for (int p = l; p <= r; ++p)
 67     {
 68         if (i <= mid && (j > r || b[i].y <= b[j].y))
 69         {
 70             add(b[i].z, b[i].cnt);
 71             a[p] = b[i++];
 72         } else {
 73             b[j].f += query(b[j].z);
 74             a[p] = b[j++];
 75         }
 76     }
 77     for (int i = l; i <= mid; ++i)
 78         add(b[i].z, -b[i].cnt);
 79     for (int i = l; i <= r; ++i)
 80         b[i] = a[i];
 81 }
 82 
 83 int main(){
 84 
 85     scanf("%d", &n);
 86     rep(i, 1, n){
 87         int x;
 88         scanf("%d", &x);
 89         a[x].x = i;
 90     }
 91 
 92     rep(i, 1, n){
 93         int x;
 94         scanf("%d", &x);
 95         a[x].y = i;
 96     }
 97 
 98     rep(i, 1, n){
 99         int x;
100         scanf("%d", &x);
101         a[x].z = i;
102     }
103 
104 //    rep(i, 1, n) printf("%d %d %d\n", a[i].x, a[i].y, a[i].z);
105 
106 
107     int sav = n;
108     init();
109     cdq(1, n);
110     LL ret = 0;
111     for (int i = 1; i <= n; ++i) ret += (LL)b[i].f;
112     printf("%lld\n", ret);
113     return 0;
114 }
View Code

Problem H

Problem I

根据题意进行模拟

不断地更新x,y的值即可

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<cstring>
 7 #include<string>
 8 #include<vector>
 9 #include<map>
10 #include<set>
11 #include<queue>
12 using namespace std;
13 char s[35];
14 int main()
15 {
16     scanf("%s",s);
17     int level=strlen(s);
18     int i;
19     int x=0,y=0;
20     for (i=0;i<level;i++)
21     {
22         int num=s[i]-'0';
23         x<<=1;
24         y<<=1;
25         if (num==1) x++;
26         else if (num==2) y++;
27         else if (num==3)
28         {
29             x++;
30             y++;
31         }
32         //cout<<x<<" "<<y<<endl;
33     }
34     printf("%d %d %d\n",level,x,y);
35     return 0;
36 }
View Code

Problem J

直接可以预处理出所有答案

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<cmath>
 7 #include<string>
 8 #include<set>
 9 #include<queue>
10 #include<map>
11 using namespace std;
12 const int inf=(1<<30)-1;
13 const int maxn=100010;
14 #define REP(i,n) for(int i=(0);i<(n);i++)
15 #define FOR(i,j,n) for(int i=(j);i<=(n);i++)
16 #define Rep(x) for(int i=head[x],y;~i;i=e[i].next) if(!vis[y=e[i].to])
17 typedef long long ll;
18 typedef pair<int,int> PII;
19 int IN(){
20     int c,f,x;
21     while (!isdigit(c=getchar())&&c!='-');c=='-'?(f=1,x=0):(f=0,x=c-'0');
22     while (isdigit(c=getchar())) x=(x<<1)+(x<<3)+c-'0';return !f?x:-x;
23 }
24 #define de(x) cout << #x << "=" << x << endl
25 #define MP make_pair
26 #define PB push_back
27 #define fi first
28 #define se second
29 int n,T;
30 int a[260],ans[260];
31 int main()
32 {
33     for(int i=0;i<256;i++)
34     a[i]=(i^(i<<1))%256,ans[a[i]]=i;
35     while(~scanf("%d",&n))
36     {
37         int x;
38         for(int i=1;i<=n;i++)
39         {
40             x=IN();
41             printf("%d%c",ans[x],i==n?'\n':' ');
42         }
43     }
44     return 0;
45 }
View Code

 

Problem K

题目看似比较复杂

其实是一个简单的计数原理

因为每顿餐都最多只有25种

所以可以直接枚举每种搭配

求出每种搭配要用到的佐料

用乘法原理进行统计

为防止溢出,在进行乘法计算时可以用除法先判断一下是否越界

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<cstring>
 7 #include<string>
 8 #include<vector>
 9 #include<map>
10 #include<set>
11 #include<queue>
12 using namespace std;
13 typedef long long ll;
14 ll r,s,m,d,n;
15 ll b[1010];
16 ll sum[1010][21];
17 bool can[1010][1010];
18 ll ans;
19 set<ll> se;
20 void calc(int x,int y,int z)
21 {
22     int i;
23     se.clear();
24     for (i=1;i<=sum[x][0];i++)
25         se.insert(sum[x][i]);
26     for (i=1;i<=sum[y][0];i++)
27         se.insert(sum[y][i]);
28     for (i=1;i<=sum[z][0];i++)
29         se.insert(sum[z][i]);
30     ll sum=1;
31     for (auto u:se)
32     {
33         if (1e18 / sum < b[u])
34         {
35             puts("too many");
36             exit(0);
37         }
38         sum=sum*b[u];
39         if (sum>1e18)
40         {
41             puts("too many");
42             exit(0);
43         }
44     }
45     ans=ans+sum;
46     if (ans>1e18)
47     {
48         puts("too many");
49         exit(0);
50     }
51 }
52 int main()
53 {
54     scanf("%lld%lld%lld%lld%lld",&r,&s,&m,&d,&n);
55     int i,j,k;
56     for (i=1;i<=r;i++)
57         scanf("%lld",&b[i]);
58     for (i=1;i<=s+m+d;i++)
59     {
60         scanf("%lld",&sum[i][0]);
61         for (j=1;j<=sum[i][0];j++)
62             scanf("%lld",&sum[i][j]);
63     }
64     memset(can,true,sizeof(can));
65     for (i=1;i<=n;i++)
66     {
67         ll x,y;
68         scanf("%lld%lld",&x,&y);
69         can[x][y]=false;
70         can[y][x]=false;
71     }
72     ans=0;
73     for (i=1;i<=s;i++)
74         for (j=s+1;j<=s+m;j++)
75             for (k=s+m+1;k<=s+m+d;k++)
76                 if (can[i][j]&&can[i][k]&&can[j][k])
77                     calc(i,j,k);
78     printf("%lld\n",ans);
79 }
View Code

 

转载于:https://www.cnblogs.com/cxhscst2/p/7631910.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值