ACM-ICPC 2018 Xuzhou Online Contest题解

首先,送上dalao的题解吧。  传送门

A. Hard to prepare    题目链接

题意:一个环形的 n 的列表每个数都是 0 到 2k1,求相邻两个数同或不为 0 的方案数。

题解:来自dalao  链接

mask[i] XNOR mask[1] >> 0 即:2进制下至少一位相同

定义:

  • dp[i][0] —— 至第ii个人分发面具的方案数,且 mask[i] = mask[1]
  • dp[i][1] —— 至第ii个人分发面具的方案数,且 mask[i] XNOR mask[1] = 0
  • dp[i][2] —— 至第ii个人分发面具的方案数,且 mask[i] ≠ mask[1],mask[i] XNOR mask[1] ≠ 0

可以推得转移方程:

  • dp[i][0]=dp[i1][0]+dp[i1][2]dp[i][0]=dp[i−1][0]+dp[i−1][2]
  • dp[i][1]=dp[i1][1]+dp[i1][2]dp[i][1]=dp[i−1][1]+dp[i−1][2]
  • dp[i][0]=(dp[i1][0]+dp[i1][1])(2k2)+dp[i1][2](2k3)
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 1e6+100;
 5 const int mod = 1e9+7;
 6 int T,n,k;
 7 long long dp[maxn][3],p[maxn];
 8 
 9 void pre()
10 {
11     p[0] = 1;
12     for (int i=1;i<=maxn-100;i++)
13     {
14         p[i] = p[i-1]+p[i-1];
15         if (p[i] >= mod) p[i]-=mod;
16     }
17     return;
18 }
19 
20 int main()
21 {
22     pre();
23     scanf("%d",&T);
24     while (T--)
25     {
26         scanf("%d %d",&n,&k);
27         dp[1][0] = 1;
28         for (int i=2;i<=n;i++)
29         {
30             dp[i][0] = (dp[i-1][0] + dp[i-1][2]) % mod;
31             dp[i][1] = (dp[i-1][1] + dp[i-1][2]) % mod;
32             dp[i][2] = (((dp[i-1][0] + dp[i-1][1])*(p[k]-2+mod)) % mod + (dp[i-1][2]*(p[k]-3+mod)) % mod) % mod;
33         }
34         long long ans = ((dp[n][0] + dp[n][2])*p[k]) % mod;
35         printf("%lld\n",ans);
36     }
37     return 0;
38 }
View Code

 

B. BE, GE or NE 题目传送门

记忆化搜索+博弈SG

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 1010;
 5 const int INF = 1e8;
 6 int n,m,l,r,a[maxn],b[maxn],c[maxn];
 7 int dp[maxn][210];
 8 
 9 int dfs(int i,int sc)
10 {
11     if (i == n+1) return sc;
12     if (dp[i][sc+100] != INF) return dp[i][sc+100];
13 
14     int cnt,tmp;
15     if (i % 2)/**first**/
16     {
17         tmp = -100;
18         if (a[i])
19         {
20             cnt = min(100,sc+a[i]);
21             tmp = max(tmp,dfs(i+1,cnt));
22         }
23         if (b[i])
24         {
25             cnt = max(-100,sc-b[i]);
26             tmp = max(tmp,dfs(i+1,cnt));
27         }
28         if (c[i])
29         {
30             cnt = sc*(-1);
31             tmp = max(tmp,dfs(i+1,cnt));
32         }
33         tmp = min(100,max(-100,tmp));
34         dp[i][sc+100] = tmp;
35     }
36     else
37     {
38         tmp = 100;
39         if (a[i])
40         {
41             cnt = min(100,sc+a[i]);
42             tmp = min(tmp,dfs(i+1,cnt));
43         }
44         if (b[i])
45         {
46             cnt = max(-100,sc-b[i]);
47             tmp = min(tmp,dfs(i+1,cnt));
48         }
49         if (c[i])
50         {
51             cnt = sc*(-1);
52             tmp = min(tmp,dfs(i+1,cnt));
53         }
54         dp[i][sc+100] = tmp;
55     }
56     return dp[i][sc+100];
57 }
58 
59 int main()
60 {
61     scanf("%d %d %d %d",&n,&m,&r,&l);
62     for (int i=1;i<=n;i++)
63         scanf("%d %d %d",&a[i],&b[i],&c[i]);
64     for (int i=0;i<=n;i++)
65         for (int j=0;j<=200;j++) dp[i][j] = INF;
66 
67     int ans = dfs(1,m);
68     if (ans >= r) printf("Good Ending\n");
69     else
70         if (ans <= l) printf("Bad Ending\n");
71     else
72         printf("Normal Ending\n");
73     return 0;
74 }
View Code

 

C. Cacti Lottery  题目传送门

我补题的时候还是不会,附上别人的暴力解法代码吧

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 int num[25] = { 0,0,0,0,0,0,10000,36,720,360,80,252,108,72,54,180,72,180,119,36,360,1080,144,1800,3600};
  5 char mp[5][5];
  6 int vis[10];
  7 int cnt = 0, cnt1 = 0, cnt2 = 0;
  8 char mp2[10];
  9 int fial[10];
 10 int idx = 0;
 11 double allans = 0;
 12 int ans[10];
 13 int A(int n, int m)
 14 {
 15     int res = 1;
 16     for (int i = 1; i <= m; i++) {
 17         res *= (n - i + 1);
 18     }
 19     return res;
 20 }
 21 void check1()
 22 {
 23     ans[0] += num[fial[0] + fial[1] + fial[2]];
 24     ans[1] += num[fial[3] + fial[4] + fial[5]];
 25     ans[2] += num[fial[6] + fial[7] + fial[8]];
 26     ans[3] += num[fial[0] + fial[3] + fial[6]];
 27     ans[4] += num[fial[1] + fial[4] + fial[7]];
 28     ans[5] += num[fial[2] + fial[5] + fial[8]];
 29     ans[6] += num[fial[0] + fial[4] + fial[8]];
 30     ans[7] += num[fial[2] + fial[4] + fial[6]];
 31 
 32 }
 33 
 34 void dfs2(int num)
 35 {
 36     if (num == 9)
 37     {
 38         check1();
 39         return;
 40     }
 41     if (fial[num] != 0) dfs2(num + 1);
 42     else {
 43         for (int i = 1; i <= 9; i++)
 44         {
 45             if (vis[i])continue;
 46             vis[i] = 1;
 47             fial[num] = i;
 48             dfs2(num + 1);
 49             fial[num] = 0;
 50             vis[i] = 0;
 51         }
 52     }
 53 }
 54 
 55 void dfs(int num)
 56 {
 57     if (num == 9)
 58     {
 59         memset(ans, 0, sizeof(ans));
 60         dfs2(0);
 61         int maxx = 0;
 62         for (int i = 0; i < 8; i++)
 63         {
 64             maxx = max(maxx, ans[i]);
 65 
 66         }
 67         /*if (maxx)
 68             cout << maxx << endl;*/
 69         allans += maxx / (A(cnt2,cnt2)*1.0);
 70         return;
 71     }
 72     if (mp2[num] == '#') { dfs(num + 1); }
 73     else if (mp2[num] != '*') { fial[num] = mp2[num] - '0'; dfs(num + 1); }
 74     else {
 75         for (int i = 1; i <= 9; i++)
 76         {
 77             if (vis[i]) continue;
 78             vis[i] = 1;
 79             fial[num] = i;
 80             dfs(num + 1);
 81             vis[i] = 0;
 82         }
 83     }
 84 }
 85 int main()
 86 {
 87     int T;
 88     scanf("%d", &T);
 89     while (T--)
 90     {
 91         memset(vis, 0, sizeof(vis));
 92         memset(fial, 0, sizeof(fial));
 93         memset(mp2, 0, sizeof(mp2));
 94         int p = 0;
 95         cnt1 = 0;
 96         cnt2 = cnt = 0;
 97         idx = 0;
 98         allans = 0;
 99         for (int i = 1; i <= 3; i++)
100         {
101             scanf("%s", mp[i]);
102             int len = strlen(mp[i]);
103             for (int j = 0; j<len; j++)
104             {
105                 if (mp[i][j] <= '9'&&mp[i][j] >= '0')
106                 {
107                     int k = mp[i][j] - '0';
108                     vis[k] = 1;
109                     cnt1++;
110                 }
111                 if (mp[i][j] == '*')
112                     cnt++;
113                 mp2[idx++] = mp[i][j];
114             }
115         }
116         cnt2 = 9 - cnt1 - cnt;
117         dfs(0);
118         int k = A(9 - cnt1, cnt);
119         double tt = allans / k * 1.0;
120         printf("%.6lf\n", tt);
121 
122     }
123     return 0;
124 }
View Code

 

D. Easy Math  题目传送门

看着题目,说是容易,dalao说这真的容易,菜鸡的我说:不会,下一个吧。 唉,还是菜。。。。。。。

看dalao在群里说过,分析出公式:   ,有篇博客也讲到了,地址传送门

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<algorithm>
  4 #include<map>
  5 #include<string>
  6 #include<math.h>
  7 #include<queue>
  8 #include<stack>
  9 #include<iostream>
 10 using namespace std;
 11 #define LL long long
 12 LL cnt, Cnt, id[1000005], B, m, H[1000005], jud[1000005], Ans, n, w[1000005], pri[1000005], Pri[100005];
 13 bool flag[1000005];
 14 void Primeset(LL n)
 15 {
 16     LL i, j;
 17     for(i=2;i<=n;i++)
 18     {
 19         if(flag[i]==0)
 20             pri[++cnt] = i;
 21         for(j=1;j<=cnt&&i*pri[j]<=n;j++)
 22         {
 23             flag[i*pri[j]] = 1;
 24             if(i%pri[j]==0)
 25                 break;
 26         }
 27     }
 28 }
 29 LL F(LL x, LL y)
 30 {
 31     LL i, k, ans;
 32     if(x<=1 || pri[y]>x)
 33         return 0;
 34     if(x>B)
 35         k = n/x;
 36     if(x<=B)
 37         k = id[x];
 38     ans = (y-1)-H[k];
 39     for(i=1;i<=Cnt;i++)
 40     {
 41         if(Pri[i]>pri[y-1] && Pri[i]<=w[k])
 42             ans++;
 43     }
 44     for(i=y;i<=cnt&&(LL)pri[i]*pri[i]<=x;i++)
 45     {
 46         if(jud[i]==0)
 47             ans = ans-F(x/pri[i], i+1);
 48     }
 49     return ans;
 50 }
 51  
 52 int main(void)
 53 {
 54     LL i, j, k, P, last, sum;
 55     scanf("%lld%lld", &n, &P);
 56     B = sqrt(n), Primeset(1000002);
 57     sum = 0;
 58     for(i=1;i<=cnt&&pri[i]*pri[i]<=P;i++)
 59     {
 60         if(P%(pri[i]*pri[i])==0)
 61         {
 62             printf("0\n");
 63             return 0;
 64         }
 65         if(P%pri[i]==0)
 66         {
 67             jud[i] = 1;
 68             Pri[++Cnt] = pri[i], sum++;
 69             P /= pri[i];
 70         }
 71     }
 72     if(P!=1)
 73     {
 74         Pri[++Cnt] = P, sum++;
 75         for(i=1;i<=cnt;i++)
 76         {
 77             if(pri[i]==P)
 78                 jud[i] = 1;
 79         }
 80     }
 81     for(i=1;i<=n;i=last+1)
 82     {
 83         w[++m] = n/i;
 84         H[m] = w[m]-1;
 85         last = n/(n/i);
 86         if(n/i<=B)
 87             id[n/i] = m;
 88     }
 89     for(j=1;j<=cnt;j++)
 90     {
 91         for(i=1;i<=m&&pri[j]*pri[j]<=w[i];i++)
 92         {
 93             if(w[i]/pri[j]<=B)
 94                 k = id[w[i]/pri[j]];
 95             else
 96                 k = n/(w[i]/pri[j]);
 97             H[i] = H[i]-(H[k]-(j-1));
 98         }
 99     }
100     Ans = F(n, 1)+1;
101     if(Cnt%2==1)
102         Ans *= -1;
103     printf("%lld\n", Ans);
104     return 0;
105 }
View Code

这篇博客讲的挺具体的。传送门

 

E. End Fantasy VIX  题目传送门

填坑,不会。

 

F. Features Track  题目传送门

模拟,判断当前的feature在前面连续出现的次数就好然后更新ans   直接暴力。(两个不同代码,供大家参考。

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<iostream>
 4 #include<string>
 5 #include<queue>
 6 #include<vector>
 7 #include<algorithm>
 8 #include<cmath>
 9 #include<set>
10 #include<map>
11 #include<stack>
12 #include<functional>
13 using namespace std;
14 #define clr(a,b) memset(a,b,sizeof(a))
15 #define lowbit(x) x&-x
16 #define rep(a,b,c) for(ll a=b;a<c;a++)
17 #define dec(a,b,c) for(int a=b;a>c;a--)
18 #define eb(x) emplace_back(x)
19 #define pb(x) push_back(x)
20 #define ps(x) push(x)
21 #define _INIT ios::sync_with_stdio(false);cin.tie(nullptr);cout.precision(10);cout<<fixed
22 #define MAX_N 100000+5
23 #define MAX_M 100
24 typedef long long ll;
25 typedef unsigned long long ull;
26 typedef priority_queue<ll,vector<ll>,greater<ll> >pqg;
27 const ll maxn=1e3;
28 const ll inf=1e7;
29 struct Node
30 {
31     int ti,x,y;
32 };
33 vector<Node> ve[MAX_N];
34 int main()
35 {
36 #ifndef ONLINE_JUDGE
37     // freopen("data.txt","r",stdin);
38 #endif
39     //_INIT;
40     int t;
41     scanf("%d",&t);
42     while(t--)
43     {
44         clr(ve,0);
45         int n,ans=0;
46         scanf("%d",&n);
47         for(int i=1; i<=n; i++)
48         {
49          int k;scanf("%d",&k);
50          while(k--)
51          {
52              Node tm;scanf("%d%d",&tm.x,&tm.y);tm.ti=i;
53              for(int j=0;j<ve[i-1].size();j++)
54              {
55                  if(ve[i-1][j].x==tm.x&&ve[i-1][j].y==tm.y){tm.ti=ve[i-1][j].ti;break;}
56              }
57              ve[i].push_back(tm);
58              ans=max(ans,i-tm.ti+1);
59          }
60         }
61         printf("%d\n",ans);
62     }
63     return 0;
64 }
View Code
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn=1e5+5;
 5 
 6 typedef pair<int,int> pii;
 7 
 8 set<pii> G[maxn];
 9 
10 int main(){
11     int t,n,m,a,b,maxl;
12     scanf("%d",&t);
13     for(int e=0;e<t;e++){
14         maxl=0;
15         for(int i=0;i<maxn;i++)G[i].clear();
16         scanf("%d",&n);
17         for(int i=0;i<n;i++){
18             scanf("%d",&m);
19             maxl=max(maxl,m);
20             for(int j=0;j<m;j++){
21                 scanf("%d%d",&a,&b);
22                 G[i].insert(pii(a,b));
23             }
24         }
25         int res=0,t=0;
26         for(int i=0;i<n;i++){
27             for(set<pii>::iterator j=G[i].begin();j!=G[i].end();j++){
28                 int l=i+1;
29                 t=1;
30                 while(l<n){
31                     if(G[l].count(*j)){
32                         G[l].erase(*j);
33                         l++;
34                         t++;
35                         res=max(res,t);
36                     }
37                     else break;
38                 }
39             }
40         }
41         printf("%d\n",res);
42     }
43 }
View Code

 

G. Trace 题目传送门 

题目分析

题意:每次给出一个点,然后就会形成两条线,如果后面的矩形覆盖了前面的边,那么这条边就消失了, 最后求剩下的边是多少

思路:分别处理x轴,y轴,然后排序,然后扫过去,每次加上自己的边长以及减去标号比自己小的并且长度比自己高的个数乘自己的边长

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 #define N 50010
  5 #define ll long long
  6 
  7 int n;
  8 
  9 struct node
 10 {
 11     int l, r;
 12     int lazy, sum;
 13     inline node() {}
 14     inline node(int _l, int _r)
 15     {
 16         l = _l, r = _r;
 17         lazy = -1;
 18         sum = 0;
 19     }
 20 }tree[N << 2];
 21 
 22 inline void pushup(int id)
 23 {
 24     tree[id].sum = tree[id << 1].sum + tree[id << 1 | 1].sum;
 25 }
 26 
 27 inline void pushdown(int id)
 28 {
 29     if (tree[id].l >= tree[id].r) return;
 30     if (~tree[id].lazy) 
 31     {
 32         int lazy = tree[id].lazy; tree[id].lazy = -1;
 33         tree[id << 1].lazy = tree[id << 1 | 1].lazy = lazy;
 34         tree[id << 1].sum = tree[id << 1 | 1].sum = 0;
 35     }
 36 }
 37 
 38 inline void build(int id, int l, int r) 
 39 {
 40     tree[id] = node(l, r);
 41     if (l == r) return;
 42     int mid = (l + r) >> 1;
 43     build(id << 1, l, mid);
 44     build(id << 1 | 1, mid + 1, r);
 45 }
 46 
 47 inline void update(int id, int l, int r, int val)
 48 {
 49     if (tree[id].l >= l && tree[id].r <= r)
 50     {
 51         tree[id].sum = val; 
 52         tree[id].lazy = val;
 53         return;
 54     }
 55     pushdown(id);
 56     int mid = (tree[id].l + tree[id].r) >> 1;
 57     if (l <= mid) update(id << 1, l, r, val); 
 58     if (r > mid) update(id << 1 | 1, l, r, val);
 59     pushup(id);
 60 }
 61 
 62 inline int query(int id, int l, int r)
 63 {
 64     if (tree[id].l >= l && tree[id].r <= r) return tree[id].sum;
 65     pushdown(id);
 66     int mid = (tree[id].l + tree[id].r) >> 1;
 67     int res = 0;
 68     if (l <= mid) res += query(id << 1, l, r);
 69     if (r > mid) res += query(id << 1 | 1, l, r);
 70     return res;
 71 }
 72 
 73 struct DT
 74 {
 75     int pos;
 76     ll x, y;
 77     inline void scan(int _pos)
 78     {
 79         pos = _pos;
 80         scanf("%lld%lld", &x, &y);
 81     }
 82 }arr[N];
 83 
 84 inline bool cmp1(DT a, DT b)
 85 {
 86     return a.x < b.x;
 87 }
 88 
 89 inline bool cmp2(DT a, DT b)
 90 {
 91     return a.y < b.y;
 92 }
 93 
 94 inline void Run()
 95 {
 96     while (scanf("%d", &n) != EOF)
 97     {
 98         for (int i = 1; i <= n; ++i) arr[i].scan(i);
 99         build(1, 1, n); 
100         sort(arr + 1, arr + 1 + n, cmp1);
101         ll res = 0;
102         for (int i = 1; i <= n; ++i)
103         {
104             res += arr[i].y;
105             int pos = query(1, 1, arr[i].pos);
106             res -= arr[i].y * pos; 
107             update(1, 1, arr[i].pos, 0);
108             update(1, arr[i].pos, arr[i].pos, 1);
109         }
110         sort(arr + 1, arr + 1 + n, cmp2);
111         update(1, 1, n, 0); 
112         for (int i = 1; i <= n; ++i)
113         {
114             res += arr[i].x;
115             int pos = query(1, 1, arr[i].pos);
116             res -= arr[i].x * pos;
117             update(1, 1, arr[i].pos, 0);
118             update(1, arr[i].pos, arr[i].pos, 1);
119         }
120         printf("%lld\n", res);
121     }
122 }
123 
124 int main()
125 {
126     #ifdef LOCAL  
127         freopen("Test.in", "r", stdin);
128     #endif  
129 
130     Run();
131     return 0;
132 }
View Code

栈维护 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 50010
 5 #define ll long long
 6 
 7 int n;
 8 
 9 struct node
10 {
11     int pos; 
12     ll x, y;
13     inline void scan(int _pos)
14     {
15         pos = _pos;
16         scanf("%lld%lld", &x, &y);
17     }
18 }arr[N];
19 
20 inline bool cmp1(node a, node b)
21 {
22     return a.x < b.x;
23 }
24 
25 inline bool cmp2(node a, node b)
26 {
27     return a.y < b.y;
28 }
29 
30 inline void Run()
31 {
32     while (scanf("%d", &n) != EOF)
33     {
34         for (int i = 1; i <= n; ++i) arr[i].scan(i);
35         sort(arr + 1, arr + 1 + n, cmp1); 
36         ll res = 0;
37         stack<int>s;
38         for (int i = 1; i <= n; ++i)
39         {
40             res += arr[i].y;
41             int cnt = 0;
42             while (!s.empty() && s.top() < arr[i].pos)
43             {
44                 cnt++;
45                 s.pop();
46             }
47             res -= cnt * arr[i].y;
48             s.push(arr[i].pos);
49         }
50         while (!s.empty())
51         {
52             s.pop();
53         }
54         sort(arr + 1, arr + 1 + n, cmp2);
55         for (int i = 1; i <= n; ++i)
56         {
57             res += arr[i].x;
58             int cnt = 0;
59             while (!s.empty() && s.top() < arr[i].pos)
60             {
61                 cnt++;
62                 s.pop();
63             }
64             res -= cnt * arr[i].x;
65             s.push(arr[i].pos);
66         }
67         printf("%lld\n", res);
68     }
69 }
70 
71 int main()
72 {
73     #ifdef LOCAL_JUDGE
74         freopen("Text.txt", "r", stdin);
75     #endif  
76 
77     Run();
78     return 0;
79 }
View Code

还有bin巨巨的暴力解法,真牛皮!链接

 

 H. Ryuji doesn't want to study 题目传送门

这题本来就是一个裸题,有一个点没考虑坑了我三小时,气死我了,真心太菜!

算一个两个不同的后缀和就行,我是强行前缀和的。

代码如下:(树状数组或者线段树,裸写)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll; 
 4 ll c[100010],a[100005],c1[100005];
 5 ll n;
 6 
 7 ll lowbit(ll x)
 8 {
 9     return x&(~x+1);
10 }
11 void Add(ll x,ll d)
12 {
13     while(x<=n)
14     {
15         c[x]+=d;
16         x+=lowbit(x);
17     }
18 }
19 ll sum(ll x)
20 {
21     ll ret=0;
22     while(x>=1)
23     {
24         ret+=c[x];
25         x-=lowbit(x);
26     }
27     return ret;
28 }
29 void Add1(ll x,ll d)
30 {
31     while(x<=n)
32     {
33         c1[x]+=d;
34         x+=lowbit(x);
35     }
36 }
37 ll sum1(ll x)
38 {
39     ll ret1=0;
40     while(x>=1)
41     {
42         ret1+=c1[x];
43         x-=lowbit(x);
44     }
45     return ret1;
46 }
47 int main()
48 {
49     ll m;
50     ios::sync_with_stdio(false);
51     cin.tie(0);
52     while(cin>>n>>m)
53     {
54         for(ll i=1; i<=n; i++)
55         {
56             //scanf("%lld",&a[i]);
57             cin>>a[i];
58             Add(i,a[i]*(n-i+1));
59             Add1(i,a[i]);
60         }
61         while(m--)
62         {
63             ll num;
64             cin>>num;
65             //scanf("%d",&num);
66             if(num==2)
67             {
68                 ll x,k;
69                 cin>>x>>k;
70                 
71                 //scanf("%lld%lld",&x,&k);
72                 Add(x,(k-a[x])*(n-x+1));
73                 Add1(x,k-a[x]);a[x]=k;
74             }
75             else if(num==1)
76             {
77                 ll x,y;
78                 //scanf("%lld%lld",&x,&y);
79                 cin>>x>>y;
80                 printf("%lld\n",sum(y)-sum(x-1)-(sum1(y)-sum1(x-1))*(n-y));
81             }
82         }
83     }
84     return 0;
85 }
View Code

 

 I. Characters with Hash 题目传送门

不想说了,也是坑了我两发,没有考虑字符串前几个字符与L字符都相同的情况。考虑步骤,刷Codeforces太少了。又懒又菜!!!

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int n,q,p,b,c,i,j;
 7     double a[100005],ans=0;
 8     scanf("%d%d",&n,&q);
 9     for(int i=0; i<n; i++)
10         scanf("%lf",&a[i]);
11     while(q--)
12     {
13         scanf("%d%d%d",&p,&b,&c);
14         ans=0;
15         int L=c-b+1;
16         switch(p)
17         {
18         case 1:
19             for(i=b-1; i<c; i++)
20                 ans+=a[i]*(L--);
21             printf("%.0f\n",ans);
22             break;
23         case 2:
24             a[b-1]=c;
25             break;
26         }
27     }
28     return 0;
29 }
View Code

 

J. Maze Designer  题目传送门   最大生成树+LCA

可以把每个格点视作视作图的点,隔开两点的边视作图的边,则构建迷宫可以视作求其生成树,剩余的边就是组成迷宫的墙.因为要花费最小,所以使删去的墙权置最大即可,呢么就是求最大生成树即可.
然后每次查询相当于查这个最大生成树上任意两点的最短距离,到这一步就是个LCA板子题了.
所以:最大生成树+树上两点最短距离。

表示我也不会lca,是时候去学习一波了。图:留下了没有技术的泪水!

  1 #include <iostream>
  2 #include <vector>
  3 #include <cstdio>
  4 #include <string>
  5 #include <cstring>
  6 #include <map>
  7 #include <algorithm>
  8 #include <queue>
  9 #include <set>
 10 #include <cmath>
 11 #include <sstream>
 12 #include <stack>
 13 #include <fstream>
 14 #include <ctime>
 15 #pragma warning(disable:4996);
 16 #define mem(sx,sy) memset(sx,sy,sizeof(sx))
 17 typedef long long ll;
 18 typedef unsigned long long ull;
 19 const double eps = 1e-8;
 20 const double PI = acos(-1.0);
 21 const ll llINF = 0x3f3f3f3f3f3f3f3f;
 22 const int INF = 0x3f3f3f3f;
 23 using namespace std;
 24 //#define pa pair<int, int>
 25 //const int mod = 1e9 + 7;
 26 const int maxn = 1000005;
 27 const int maxq = 300005;
 28 struct node {
 29     int u, v, w, next, lca;
 30 };
 31  
 32 struct LCA {
 33     node edges[maxn], ask[maxq];
 34     int ghead[maxn], gcnt, ahead[maxn], acnt;
 35     int anc[maxn];
 36     int vis[maxn];
 37     ll dist[maxn];
 38     int fa[maxn];
 39  
 40     void addedge(int u, int v, int w) {
 41         edges[gcnt].v = v;
 42         edges[gcnt].w = w;
 43         edges[gcnt].next = ghead[u];
 44         ghead[u] = gcnt++;
 45     }
 46     
 47     void addask(int u, int v) {
 48         ask[acnt].u = u;
 49         ask[acnt].v = v;
 50         ask[acnt].next = ahead[u];
 51         ahead[u] = acnt++;
 52     }
 53     
 54     void init() {
 55         mem(vis, 0);
 56         mem(ghead, -1);
 57         mem(ahead, -1);
 58         gcnt = 0;
 59         acnt = 0;
 60     }
 61  
 62     int Find(int x) {
 63         return fa[x] == x ? x : (fa[x] = Find(fa[x]));
 64     }
 65  
 66     void getLCA(int u, int d) {
 67         dist[u] = d;
 68         fa[u] = u;
 69         vis[u] = 1;
 70         for (int i = ghead[u]; i != -1; i = edges[i].next) {
 71             int v = edges[i].v;
 72             if (!vis[v]) {
 73                 getLCA(v, d + edges[i].w);
 74                 fa[v] = u;
 75                 anc[fa[v]] = u;
 76             }
 77         }
 78         for (int i = ahead[u]; i != -1; i = ask[i].next) {
 79             int v = ask[i].v;
 80             if (vis[v])
 81                 ask[i].lca = ask[i ^ 1].lca = Find(ask[i].v);
 82         }
 83  
 84     }
 85  
 86 }L;
 87  
 88 struct edge {
 89     int u, v;
 90     ll w;
 91     bool operator<(const edge &e)const { return w>e.w; }
 92     edge(int _u = 0, int  _v = 0, ll _w = 0)
 93         :u(_u), v(_v), w(_w) {}
 94 };
 95  
 96 struct Kruskal {
 97     int n, m;
 98     edge edges[maxn];
 99     int fa[maxn];
100     int Find(int x) {
101         return fa[x] == -1 ? x : fa[x] = Find(fa[x]);
102     }
103     void init(int _n) {
104         this->n = _n;
105         m = 0;
106         mem(fa, -1);
107     }
108  
109     void AddEdge(int u, int v, ll dist) {
110         edges[m++] = edge(u, v, dist);
111     }
112  
113     ll kruskal() {
114         ll sum = 0;
115         int cntnum = 0;
116         sort(edges, edges + m);
117         for (int i = 0; i < m; i++) {
118             int u = edges[i].u, v = edges[i].v;
119             if (Find(u) != Find(v)) {
120                 L.addedge(u, v, 1);
121                 L.addedge(v, u, 1);
122                 //cout << u << " " << v << endl;
123                 sum += edges[i].w;
124                 fa[Find(u)] = Find(v);
125                 if (++cntnum >= n - 1) return sum;
126             }
127         }
128         return -1;
129     }
130 }G;
131  
132 int main() {
133     int n, m;
134     while (~scanf("%d%d", &n, &m)) {
135         G.init(n*m);
136         L.init();
137         for (int i = 1; i <= n; ++i) {
138             for (int j = 1; j <= m; ++j) {
139                 int w1, w2; char c1, c2;
140                 scanf(" %c%d %c%d", &c1, &w1, &c2, &w2);
141                 if (c1 == 'D') {
142                     G.AddEdge((i - 1)*m + j, i*m + j, w1);
143                 }
144                 if (c2 == 'R') {
145                     G.AddEdge((i - 1)*m + j, (i - 1)*m + j + 1, w2);
146                 }
147             }
148         }
149         G.kruskal();
150         int q;
151         scanf("%d", &q);
152         for (int i = 1, x1, x2, y1, y2; i <= q; i++) {
153             scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
154             int u = (x1 - 1)*m + y1;
155             int v = (x2 - 1)*m + y2;
156             L.addask(u, v);
157             L.addask(v, u);
158         }
159         L.getLCA(1, 0);
160         for (int i = 0; i < L.acnt; i += 2) {
161             printf("%lld\n", L.dist[L.ask[i].u] + L.dist[L.ask[i].v] - 2 * L.dist[L.ask[i].lca]);
162         }
163     }
164 }
View Code

 

K. Morgana Net  题目传送门

矩阵快速幂  dalao的分析如下

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int T,n,m,t;
 5 int a[20][20],b[20][20];
 6 
 7 struct Matrix
 8 {
 9     int n,m,d[70][70];
10     Matrix (int N=0, int M=0)
11     {
12         n = N, m = M;
13         memset(d,0,sizeof(d));
14     }
15     friend Matrix operator * (const Matrix &a, const Matrix &b)
16     {
17         Matrix c(a.n,b.m);
18         for (int i=0;i<a.n;i++)
19             for (int j=0;j<b.m;j++)
20             {
21                 long long tmp = 0;
22                 for (int k=0;k<a.m;k++)
23                     tmp += (a.d[i][k]*b.d[k][j] & 1);
24                 c.d[i][j] = tmp & 1;
25             }
26         return c;
27     }
28 };
29 
30 void solve()
31 {
32     Matrix A(1,n*n),B(n*n,n*n);
33     m = m/2;
34     for (int i=0;i<n;i++)
35         for (int j=0;j<n;j++)
36         {
37             A.d[0][i*n+j] = a[i][j] & 1;
38             for (int p = i-m; p <= i+m; p++)
39                 for (int q = j-m; q <= j+m; q++)
40                 {
41                     if (p < 0 || q < 0 || p >= n || q >= n) continue;
42                     B.d[p*n+q][i*n+j] = b[p-i+m][q-j+m] & 1;
43                 }
44         }
45 
46     while (t)
47     {
48         if (t & 1) A = A*B;
49         B = B*B;
50         t = t>>1;
51     }
52     int ans = 0;
53     for (int i=0;i<n*n;i++) ans += A.d[0][i];
54     printf("%d\n",ans);
55     return;
56 }
57 
58 int main()
59 {
60     scanf("%d",&T);
61     while (T--)
62     {
63         scanf("%d %d %d",&n,&m,&t);
64         for (int i=0;i<n;i++)
65             for (int j=0;j<n;j++) scanf("%d",&a[i][j]);
66         for (int i=0;i<m;i++)
67             for (int j=0;j<m;j++) scanf("%d",&b[i][j]);
68         solve();
69     }
70     return 0;
71 }
View Code

 

  这次比赛打完之后,整个人都是崩溃的,这场的题目很好,坑点很多,前面两道签到题目我都是签了一个小时多,我无语了。感觉自己的练习题量特少,每天感觉都是浑浑噩噩的过着,都不知道自己在干啥,大四了,感觉太浪了,需要冷静下来想想,接下来要学习什么东西。别一天到晚东学一个算法西学一个小程序,感觉自己没有规划,一天到晚漫无目的的过着。

  接下来还是老老实实学习算法吧,每天坚持刷题。学习微信小程序的全栈开发。(估计没什么机会去参加比赛了。。。。自己上半年和暑期都没有刷题。。。。。太菜了QAQ。别为自己的菜找理由,埋下头来学习就行,别浪!。

  终于写完了,溜了溜了。

posted @ 2018-09-10 23:40  FantasticSpeed  阅读(333)  评论(0编辑  收藏  举报