2018 Multi-University Training Contest 6
不知不觉拖欠了两周阿哈哈哈哈或
1001 oval-and-rectangle
谈学姐最喜欢积分了 不写SPJ最牛逼了
1 #include<bits/stdc++.h> 2 using namespace std; 3 long long T,a,b,i,j,k,s,t; 4 double ans,temp=asin(1.0); 5 int main() 6 { 7 scanf("%lld",&T); 8 while (T--) 9 { 10 scanf("%lld%lld",&a,&b); 11 ans=2*b+2*a*temp; 12 s=(long long) (ans*1000000); 13 ans=s*0.000001; 14 printf("%.6f\n",ans); 15 } 16 }
1002 bookshelf
就俩结论$gcd(2^a - 1, 2^b - 1) = 2^{gcd(a, b)} - 1$,这个其实就是辗转相除的过程
$gcd(fib[a], fib[b]) = fib[gcd(a, b)]$,这个有点麻烦吧百度有一堆证明,敝队比较菜打表看出来的
问题就转变为求$gcd$为$g$的整数拆分,因为$g$要是$n$的约数,根号拆分暴力容斥一下就好了
1 #include<bits/stdc++.h> 2 using namespace std; 3 long long ans,n,i,j,k,s,t,sum,mod=1e9+7; 4 long long a[1000010],b[1000010],mob[1000010],f[1000010],fac[2000010],invfac[2000010]; 5 long long ksm(long long x,long long y,long long mod) 6 { 7 long long temp=1; 8 x%=mod; 9 while (y>0) 10 { 11 if (y%2==1) temp=temp*x%mod; 12 x=x*x%mod; 13 y/=2; 14 } 15 return temp; 16 } 17 long long cc(long long n,long long m) 18 { 19 long long temp=fac[n]*invfac[m]%mod; 20 temp=temp*invfac[n-m]%mod; 21 return temp; 22 } 23 int main() 24 { 25 f[1]=1;f[2]=1; 26 for (i=3;i<=1000000;i++) 27 { 28 f[i]=((f[i-1]+1)*(f[i-2]+1)-1)%mod; 29 } 30 fac[0]=invfac[0]=1; 31 for (i=1;i<=2000000;i++) 32 { 33 fac[i]=fac[i-1]*i%mod; 34 } 35 invfac[2000000]=ksm(fac[2000000],mod-2,mod); 36 for (i=1999999;i>=1;i--) 37 { 38 invfac[i]=invfac[i+1]*(i+1)%mod; 39 } 40 sum=0; 41 mob[1]=1; 42 for (i=2;i<=1000000;i++) 43 { 44 if (a[i]==0) 45 { 46 sum++; 47 b[sum]=i; 48 mob[i]=-1; 49 } 50 for (j=1;j<=sum;j++) 51 { 52 s=i*b[j]; 53 if (s>100000) break; 54 a[s]=1; 55 mob[s]=-mob[i]; 56 if (i%b[j]==0) 57 { 58 mob[s]=0; 59 break; 60 } 61 } 62 } 63 int T; 64 scanf("%d",&T); 65 while (T--) 66 { 67 scanf("%lld%lld",&n,&k); 68 ans=0;s=0;sum=0; 69 for (i=1;i<=int(sqrt(n));i++) 70 { 71 if (n%i==0) 72 { 73 sum++; 74 a[sum]=i; 75 b[sum]=n/i; 76 } 77 } 78 t=sum; 79 if (a[t]==b[t]) t--; 80 for (i=t;i>=1;i--) 81 { 82 sum++; 83 a[sum]=b[i]; 84 } 85 for (i=1;i<=sum;i++) b[i]=cc(n/a[i]+k-1,k-1); 86 for (i=sum;i>=1;i--) 87 { 88 if (n%a[i]==0) 89 { 90 t=b[i]; 91 ans=(ans+f[a[i]]*t)%mod; 92 for (j=1;j<i;j++) 93 if (a[i]%a[j]==0) b[j]=(b[j]-b[i])%mod; 94 } 95 } 96 s=cc(n+k-1,k-1); 97 ans=ans*ksm(s,mod-2,mod)%mod; 98 if (ans<0) ans+=mod; 99 printf("%lld\n",ans); 100 } 101 }
1003 Ringland
首先容易看出来是枚举一个起点,然后顺序匹配下去最优
因为距离是$\min(|a_{i} - b_{j}|, L - |a_{i} - b_{j}|)$,把$b$开三倍就可以断环为链,问题转化为$\min\limits_{bias} \sum_{i = 1} ^{n} |a_{i} - b_{i + bias}|$
这样$a_{i}$和$b_{i}$的贡献都只有正负两种,只要找到正负分界点,对第二段$b$维护最大的小于$b_{i}$的$a_{p}$位置双指针扫一遍即可
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 5e5 + 10; 5 int a[maxn], b[maxn * 3]; 6 ll del[maxn * 2]; 7 8 int main() { 9 int T; 10 scanf("%d", &T); 11 while(T--) { 12 int N, L, p = 1; 13 scanf("%d %d", &N, &L); 14 for(int i = 1; i <= N; ++i) scanf("%d", a + i); 15 for(int i = 1; i <= N; ++i) { 16 scanf("%d", b + N + i); 17 b[i] = b[N + i] - L; 18 b[N + N + i] = b[N + i] + L; 19 } 20 for(int i = 1; i <= N + N + 1; ++i) del[i] = 0; 21 for(int i = 1; i <= N; ++i) { 22 del[1] += a[i] - b[i]; 23 del[i + 1] += b[i]; 24 del[i + N + 1] += b[i + N + N]; 25 } 26 for(int i = N + 1; i <= N + N; ++i) { 27 while(p <= N && a[p] <= b[i]) del[i - p + 2] -= 2 * a[p++]; 28 del[i - N + 1] -= b[i]; 29 del[i - p + 2] += 2 * b[i]; 30 del[i + 1] -= b[i]; 31 } 32 while(p <= N) del[N + N + 3 - p] -= 2 * a[p++]; 33 ll t = 0, ans = 1e18; 34 for(int i = 1; i <= N + N + 1; ++i) t += del[i], ans = min(ans, t); 35 printf("%lld\n", ans); 36 } 37 return 0; 38 }
1004 Shoot Game
看完题解恍然大悟?其实状态并不是那么好想呀……
因为要$f[i][j]$表示消除被区间$[i, j]$完全包含的线段,然后枚举中间点$k$时,被$[i, j]$完全包含而不被$[i, k - 1]$或者$[k + 1, j]$包含的一定经过$k$了
每次枚举最大的转移,如果这个区间没有包含任何线段就是$0$,多个最大的没有影响……
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll inf = 1e18; 5 int H[333], L[333], R[333], W[333]; 6 ll f[666][666]; 7 struct P { 8 int y, x; 9 friend bool operator < (P A, P B) { 10 return 1ll * A.x * B.y < 1ll * B.x * A.y; 11 } 12 friend bool operator == (P A, P B) { 13 return !(A < B) && !(B < A); 14 } 15 }; 16 vector<P> v; 17 18 int main() { 19 int T; 20 scanf("%d", &T); 21 while(T--) { 22 int n; 23 scanf("%d", &n); 24 v.clear(); 25 for(int i = 1; i <= n; ++i) { 26 scanf("%d %d %d %d", H + i, L + i, R + i, W + i); 27 v.emplace_back(P{H[i], L[i]}); 28 v.emplace_back(P{H[i], R[i]}); 29 } 30 sort(v.begin(), v.end()); 31 v.erase(unique(v.begin(), v.end()), v.end()); 32 int sz = v.size(); 33 for(int i = 1; i <= n; ++i) { 34 L[i] = lower_bound(v.begin(), v.end(), P{H[i], L[i]}) - v.begin() + 1; 35 R[i] = lower_bound(v.begin(), v.end(), P{H[i], R[i]}) - v.begin() + 1; 36 } 37 for(int l = 1; l <= sz; ++l) { 38 for(int s = 1; s + l - 1 <= sz; ++s) { 39 int e = s + l - 1, mx = -1, p = 0; 40 f[s][e] = inf; 41 for(int i = 1; i <= n; ++i) { 42 if(s <= L[i] && R[i] <= e && W[i] > mx) 43 mx = W[i], p = i; 44 } 45 if(!p) f[s][e] = 0; 46 else for(int i = L[p]; i <= R[p]; ++i) { 47 f[s][e] = min(f[s][e], f[s][i - 1] + mx + f[i + 1][e]); 48 } 49 } 50 } 51 printf("%lld\n", f[1][sz]); 52 } 53 return 0; 54 }
1005 black-and-white
观察一下发现必有一点是在所在行/列的最靠边的一个黑格,这样的黑格是$O(n)$的,如果两个都是靠边的可以$O(n^2)$暴力一下
否则枚举不靠边的那个点,另一个靠边的点只能在四个角的矩形范围内,比较好写的方法是预处理每个点左上角中靠边点$i + j$的最小值和数目,然后翻三次
看了题解感觉想法挺简单的……写着写着就自闭了……
1 #include <bits/stdc++.h> 2 using namespace std; 3 short L[2005][2005], U[2005][2005]; 4 bool G[2005][2005], b[2005][2005]; 5 short f[2005][2005], g[2005][2005]; 6 char s[2005]; 7 8 int mx, num; 9 inline void up(int x, int y = 1) { 10 if(x == mx) num += y; 11 else if(x > mx) mx = x, num = y; 12 } 13 14 inline void flip(int N) { 15 static bool G_[2005][2005], b_[2005][2005]; 16 for(int i = 1; i <= N; ++i) 17 for(int j = 1; j <= N; ++j) 18 G_[i][j] = G[i][j], b_[i][j] = b[i][j]; 19 for(int i = 1; i <= N; ++i) 20 for(int j = 1; j <= N; ++j) 21 G[i][j] = G_[N + 1 - j][i], b[i][j] = b_[N + 1 - j][i]; 22 } 23 24 typedef pair<int, int> pii; 25 vector<pii> v; 26 int main() { 27 int T; 28 scanf("%d", &T); 29 while(T--) { 30 mx = -1, num = 0; 31 int N; 32 scanf("%d", &N); 33 for(int i = 1; i <= N; ++i) { 34 scanf("%s", s + 1); 35 for(int j = 1; j <= N; ++j) G[i][j] = s[j] == '1', b[i][j] = 0; 36 } 37 // 同行同列 38 for(int i = 1; i <= N; ++i) { 39 int col = 0, fi = 0; 40 for(int j = 1; j <= N; ++j) { 41 if(G[i][j]) { 42 L[i][j] = L[i][j - 1] + 1, U[i][j] = U[i - 1][j] + 1; 43 if(!col) b[i][j] = 1, fi = j; 44 col = j; 45 } 46 else L[i][j] = U[i][j] = 0; 47 } 48 if(col && col - L[i][col] + 1 > fi) up(col - fi); 49 b[i][col] = 1; 50 } 51 for(int j = N; j >= 1; --j) { 52 int row = 0, fi = 0; 53 for(int i = N; i >= 1; --i) { 54 if(G[i][j]) { 55 if(!row) b[i][j] = 1, fi = i; 56 row = i; 57 } 58 } 59 if(row && fi - U[fi][j] + 1 > row) up(fi - row); 60 b[row][j] = 1; 61 } 62 v.clear(); 63 for(int i = 1; i <= N; ++i) { 64 for(int j = 1; j <= N; ++j) { 65 if(b[i][j]) v.emplace_back(pii(i, j)); 66 } 67 } 68 // 两边缘 69 int sz = v.size(); 70 for(int i = 0; i < sz; ++i) { 71 int x1 = v[i].first, y1 = v[i].second; 72 for(int j = i + 1; j < sz; ++j) { 73 int x2 = v[j].first, y2 = v[j].second; 74 if(x1 == x2 || y1 == y2) continue; 75 if(y1 > y2) { 76 if(y1 - L[x2][y1] + 1 <= y2 && x2 - U[x2][y1] + 1 <= x1) continue; 77 if(y1 - L[x1][y1] + 1 <= y2 && x2 - U[x2][y2] + 1 <= x1) continue; 78 up(y1 - y2 + x2 - x1); 79 } 80 else { 81 if(y2 - L[x2][y2] + 1 <= y1 && x2 - U[x2][y1] + 1 <= x1) continue; 82 if(y2 - L[x1][y2] + 1 <= y1 && x2 - U[x2][y2] + 1 <= x1) continue; 83 up(y2 - y1 + x2 - x1); 84 } 85 } 86 } 87 // 一边缘 88 for(int d = 0; d < 4; ++d) { 89 if(d) { 90 flip(N); 91 for(int i = 1; i <= N; ++i) 92 for(int j = 1; j <= N; ++j) 93 if(G[i][j]) L[i][j] = L[i][j - 1] + 1, U[i][j] = U[i - 1][j] + 1; 94 else L[i][j] = U[i][j] = 0; 95 } 96 for(int i = 0; i <= N; ++i) 97 for(int j = 0; j <= N; ++j) 98 f[i][j] = 3 * N; 99 for(int i = 1; i <= N; ++i) { 100 for(int j = 1; j <= N; ++j) { 101 int mx = min(f[i - 1][j], f[i][j - 1]), x = 0; 102 if(b[i][j] && i + j < mx) mx = i + j; 103 if(f[i - 1][j] == mx) x += g[i - 1][j]; 104 if(f[i][j - 1] == mx) x += g[i][j - 1]; 105 if(f[i - 1][j - 1] == mx) x -= g[i - 1][j - 1]; 106 if(b[i][j] && i + j == mx) x++; 107 f[i][j] = mx, g[i][j] = x; 108 if(G[i][j] && !b[i][j]) { 109 if(L[i][j] == j || U[i][j] == i) continue; 110 int x = i - U[i][j], y = j - L[i][j]; 111 up(i + j - f[x][y], g[x][y]); 112 } 113 } 114 } 115 } 116 printf("%d %d\n", mx, num); 117 } 118 return 0; 119 }
1006 foam-transformation
因为T操作是加一个二次函数,相当于对三次差分后随便选相邻两个位置$+x$,因此问题等价于多少个子串交错和为$0$
又可以证明,后面加了五个零后,三次差分交错和为$0$,原数列交错和也为$0$,只需维护原数列交错和
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e5 + 10; 5 ll a[maxn], sum[maxn], ans; 6 map<ll, int> mp; 7 8 inline void upd(int i, int x) { 9 mp[sum[i]]--; 10 ans -= mp[sum[i]]; 11 if(i & 1) sum[i] += x; 12 else sum[i] -= x; 13 ans += mp[sum[i]]; 14 mp[sum[i]]++; 15 } 16 17 int main() { 18 int T; 19 scanf("%d", &T); 20 while(T--) { 21 int n, m; 22 scanf("%d %d", &n, &m); 23 mp.clear(); 24 mp[0] = 1; 25 ans = 0; 26 for(int i = 1; i <= n; ++i) { 27 scanf("%lld", a + i); 28 if(i & 1) sum[i] = sum[i - 1] + a[i]; 29 else sum[i] = sum[i - 1] - a[i]; 30 ans += mp[sum[i]]; 31 mp[sum[i]]++; 32 } 33 printf("%lld\n", ans); 34 while(m--) { 35 int i, x; 36 char s[11]; 37 scanf("%s%d%d", s, &i, &x); 38 upd(i, x); 39 printf("%lld\n", ans); 40 } 41 } 42 return 0; 43 }
1007 Variance-MST
LOJ #2469……应该不补了
1008 Rectangle Outline
题解证明了一个轮廓线最多不超过$8n$个拐点,考虑扫描线去抠边界,就是覆盖次数由$0$变成$1$的区间,用线段树暴力抠,因为不超过$8n$,如果某一次超过就直接跳出
抠出来以后建图判断一下是不是一个环
不想动脑子,四个方向的部分直接copy-paste了
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1e5 + 10; 4 typedef pair<int, int> pii; 5 int mx[maxn], my[maxn], Mx[maxn], My[maxn]; 6 vector<int> b; 7 8 struct seg { 9 int h, l, r, o; 10 }; 11 vector<seg> S; 12 bool cmp1(seg A, seg B) { 13 if(A.h != B.h) return A.h < B.h; 14 return A.o > B.o; 15 } 16 bool cmp2(seg A, seg B) { 17 if(A.h != B.h) return A.h > B.h; 18 return A.o > B.o; 19 } 20 21 int M[maxn << 4], mi[maxn << 4], tag[maxn << 4]; 22 inline void gather(int p) { 23 M[p] = max(M[p << 1], M[p << 1 | 1]); 24 mi[p] = min(mi[p << 1], mi[p << 1 | 1]); 25 } 26 inline void push(int p) { 27 if (tag[p]) { 28 tag[p << 1] += tag[p]; 29 tag[p << 1 | 1] += tag[p]; 30 M[p << 1] += tag[p]; 31 M[p << 1 | 1] += tag[p]; 32 mi[p << 1] += tag[p]; 33 mi[p << 1 | 1] += tag[p]; 34 tag[p] = 0; 35 } 36 } 37 void build(int p, int l, int r) { 38 tag[p] = 0; 39 if (l < r) { 40 int mid = (l + r) >> 1; 41 build(p << 1, l, mid); 42 build(p << 1 | 1, mid + 1, r); 43 gather(p); 44 } else M[p] = mi[p] = 0; 45 } 46 void modify(int p, int tl, int tr, int l, int r, int v) { 47 if (tl > tr) return; 48 if (tr < l || r < tl) return; 49 if (l <= tl && tr <= r) { 50 tag[p] += v; 51 M[p] += v; 52 mi[p] += v; 53 return; 54 } 55 push(p); 56 int mid = (tl + tr) >> 1; 57 modify(p << 1, tl, mid, l, r, v); 58 modify(p << 1 | 1, mid + 1, tr, l, r, v); 59 gather(p); 60 } 61 vector<pii> ret; 62 void query(int p, int tl, int tr, int l, int r) { 63 if (tl > tr) return; 64 if (tr < l || r < tl) return; 65 if (mi[p] > 0) return; 66 if (l <= tl && tr <= r && M[p] == 0) { 67 ret.emplace_back(pii(tl - 1, tr)); 68 return; 69 } 70 push(p); 71 int mid = (tl + tr) >> 1; 72 query(p << 1, tl, mid, l, r), query(p << 1 | 1, mid + 1, tr, l, r); 73 } 74 75 map< pii, vector<pii> > G; 76 vector<pii> ans; 77 void get(pii x, pii f, pii rt) { 78 int ok = 1; 79 while(ok) { 80 ok = 0; 81 ans.push_back(x); 82 for(int i = 0; i < G[x].size(); ++i) { 83 pii to = G[x][i]; 84 if(to == f || to == rt) continue; 85 ok = 1, f = x, x = to; break; 86 } 87 } 88 } 89 int main() { 90 int T; 91 scanf("%d", &T); 92 while(T--) { 93 int n, ok = 1; 94 scanf("%d", &n); 95 b.clear(); 96 for(int i = 1; i <= n; ++i) { 97 scanf("%d %d %d %d", mx + i, my + i, Mx + i, My + i); 98 b.push_back(mx[i]), b.push_back(my[i]); 99 b.push_back(Mx[i]), b.push_back(My[i]); 100 } 101 sort(b.begin(), b.end()); 102 b.erase(unique(b.begin(), b.end()), b.end()); 103 for(int i = 1; i <= n; ++i) { 104 mx[i] = lower_bound(b.begin(), b.end(), mx[i]) - b.begin(); 105 my[i] = lower_bound(b.begin(), b.end(), my[i]) - b.begin(); 106 Mx[i] = lower_bound(b.begin(), b.end(), Mx[i]) - b.begin(); 107 My[i] = lower_bound(b.begin(), b.end(), My[i]) - b.begin(); 108 } 109 G.clear(); 110 S.clear(); 111 for(int i = 1; i <= n; ++i) { 112 S.emplace_back(seg{mx[i], my[i], My[i], 1}); 113 S.emplace_back(seg{Mx[i], my[i], My[i], -1}); 114 } 115 sort(S.begin(), S.end(), cmp1); 116 build(1, 1, b.size()); 117 for(int i = 0; i < S.size(); ++i) { 118 if(S[i].o == -1) { 119 modify(1, 1, b.size(), S[i].l + 1, S[i].r, -1); 120 continue; 121 } 122 int j = i; 123 while(j + 1 < S.size() && S[j + 1].h == S[j].h && S[j + 1].o == 1) ++j; 124 ret.clear(); 125 for(int k = i; k <= j; ++k) { 126 query(1, 1, b.size(), S[k].l + 1, S[k].r); 127 modify(1, 1, b.size(), S[k].l + 1, S[k].r, 1); 128 } 129 sort(ret.begin(), ret.end()); 130 vector<pii> tmp; 131 for(int k = 0; k < ret.size(); ++k) { 132 int sz = tmp.size(); 133 if(sz && tmp[sz - 1].second >= ret[k].first) { 134 ret[k] = pii(tmp[sz - 1].first, ret[k].second); 135 tmp.pop_back(), tmp.push_back(ret[k]); 136 } 137 else tmp.push_back(ret[k]); 138 } 139 for(int k = 0; k < tmp.size(); ++k) { 140 G[pii(S[i].h, tmp[k].first)].emplace_back(pii(S[i].h, tmp[k].second)); 141 G[pii(S[i].h, tmp[k].second)].emplace_back(pii(S[i].h, tmp[k].first)); 142 } 143 if(G.size() >= 8 * n) {ok = 0; break;} 144 i = j; 145 } 146 if(!ok) {puts("Oops!"); continue;} 147 S.clear(); 148 for(int i = 1; i <= n; ++i) { 149 S.emplace_back(seg{Mx[i], my[i], My[i], 1}); 150 S.emplace_back(seg{mx[i], my[i], My[i], -1}); 151 } 152 sort(S.begin(), S.end(), cmp2); 153 build(1, 1, b.size()); 154 for(int i = 0; i < S.size(); ++i) { 155 if(S[i].o == -1) { 156 modify(1, 1, b.size(), S[i].l + 1, S[i].r, -1); 157 continue; 158 } 159 int j = i; 160 while(j + 1 < S.size() && S[j + 1].h == S[j].h && S[j + 1].o == 1) ++j; 161 ret.clear(); 162 for(int k = i; k <= j; ++k) { 163 query(1, 1, b.size(), S[k].l + 1, S[k].r); 164 modify(1, 1, b.size(), S[k].l + 1, S[k].r, 1); 165 } 166 sort(ret.begin(), ret.end()); 167 vector<pii> tmp; 168 for(int k = 0; k < ret.size(); ++k) { 169 int sz = tmp.size(); 170 if(sz && tmp[sz - 1].second >= ret[k].first) { 171 ret[k] = pii(tmp[sz - 1].first, ret[k].second); 172 tmp.pop_back(), tmp.push_back(ret[k]); 173 } 174 else tmp.push_back(ret[k]); 175 } 176 for(int k = 0; k < tmp.size(); ++k) { 177 G[pii(S[i].h, tmp[k].first)].emplace_back(pii(S[i].h, tmp[k].second)); 178 G[pii(S[i].h, tmp[k].second)].emplace_back(pii(S[i].h, tmp[k].first)); 179 } 180 if(G.size() >= 8 * n) {ok = 0; break;} 181 i = j; 182 } 183 if(!ok) {puts("Oops!"); continue;} 184 S.clear(); 185 for(int i = 1; i <= n; ++i) { 186 S.emplace_back(seg{my[i], mx[i], Mx[i], 1}); 187 S.emplace_back(seg{My[i], mx[i], Mx[i], -1}); 188 } 189 sort(S.begin(), S.end(), cmp1); 190 build(1, 1, b.size()); 191 for(int i = 0; i < S.size(); ++i) { 192 if(S[i].o == -1) { 193 modify(1, 1, b.size(), S[i].l + 1, S[i].r, -1); 194 continue; 195 } 196 int j = i; 197 while(j + 1 < S.size() && S[j + 1].h == S[j].h && S[j + 1].o == 1) ++j; 198 ret.clear(); 199 for(int k = i; k <= j; ++k) { 200 query(1, 1, b.size(), S[k].l + 1, S[k].r); 201 modify(1, 1, b.size(), S[k].l + 1, S[k].r, 1); 202 } 203 sort(ret.begin(), ret.end()); 204 vector<pii> tmp; 205 for(int k = 0; k < ret.size(); ++k) { 206 int sz = tmp.size(); 207 if(sz && tmp[sz - 1].second >= ret[k].first) { 208 ret[k] = pii(tmp[sz - 1].first, ret[k].second); 209 tmp.pop_back(), tmp.push_back(ret[k]); 210 } 211 else tmp.push_back(ret[k]); 212 } 213 for(int k = 0; k < tmp.size(); ++k) { 214 G[pii(tmp[k].first, S[i].h)].emplace_back(pii(tmp[k].second, S[i].h)); 215 G[pii(tmp[k].second, S[i].h)].emplace_back(pii(tmp[k].first, S[i].h)); 216 } 217 if(G.size() >= 8 * n) {ok = 0; break;} 218 i = j; 219 } 220 if(!ok) {puts("Oops!"); continue;} 221 S.clear(); 222 for(int i = 1; i <= n; ++i) { 223 S.emplace_back(seg{My[i], mx[i], Mx[i], 1}); 224 S.emplace_back(seg{my[i], mx[i], Mx[i], -1}); 225 } 226 sort(S.begin(), S.end(), cmp2); 227 build(1, 1, b.size()); 228 for(int i = 0; i < S.size(); ++i) { 229 if(S[i].o == -1) { 230 modify(1, 1, b.size(), S[i].l + 1, S[i].r, -1); 231 continue; 232 } 233 int j = i; 234 while(j + 1 < S.size() && S[j + 1].h == S[j].h && S[j + 1].o == 1) ++j; 235 ret.clear(); 236 for(int k = i; k <= j; ++k) { 237 query(1, 1, b.size(), S[k].l + 1, S[k].r); 238 modify(1, 1, b.size(), S[k].l + 1, S[k].r, 1); 239 } 240 sort(ret.begin(), ret.end()); 241 vector<pii> tmp; 242 for(int k = 0; k < ret.size(); ++k) { 243 int sz = tmp.size(); 244 if(sz && tmp[sz - 1].second >= ret[k].first) { 245 ret[k] = pii(tmp[sz - 1].first, ret[k].second); 246 tmp.pop_back(), tmp.push_back(ret[k]); 247 } 248 else tmp.push_back(ret[k]); 249 } 250 for(int k = 0; k < tmp.size(); ++k) { 251 G[pii(tmp[k].first, S[i].h)].emplace_back(pii(tmp[k].second, S[i].h)); 252 G[pii(tmp[k].second, S[i].h)].emplace_back(pii(tmp[k].first, S[i].h)); 253 } 254 if(G.size() >= 8 * n) {ok = 0; break;} 255 i = j; 256 } 257 if(!ok) {puts("Oops!"); continue;} 258 ans.clear(); 259 pii st = (*G.begin()).first; 260 if(G[st].size() != 2) {puts("Oops!"); continue;} 261 if(G[st][0].first == st.first) get(st, G[st][1], st); 262 else get(st, G[st][0], st); 263 if(ans.size() != G.size()) {puts("Oops!"); continue;} 264 printf("%d\n", ans.size()); 265 for(int i = 0; i < ans.size(); ++i) printf("%d %d\n", b[ans[i].first], b[ans[i].second]); 266 } 267 return 0; 268 }
1009 Werewolf
其实窝感觉这题还是有点意思的,就是$Clar$里一堆人不懂题意……
首先第一个数肯定是$0$,就当大家说的都是废话没事发生过
然后铁狼只有唯一的情况,就是某人$A$指认狼$B$,被指认人$B$却通过一串民直接或间接指认$A$为民,那么$B$和所有直接间接指认$B$为民的都是狼
只要对所有指民的边反向建图,以每个指狼的为起点反向随便遍历两边就好了
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1e5 + 10; 4 vector<int> G[maxn]; 5 int a[maxn]; 6 7 bool dfs(int x, int tar) { 8 if(x == tar) return true; 9 for(int i = 0; i < G[x].size(); ++i) { 10 int to = G[x][i]; 11 if(dfs(to, tar)) return true; 12 } 13 return false; 14 } 15 16 int rdfs(int x) { 17 int ret = 1; 18 for(int i = 0; i < G[x].size(); ++i) { 19 int to = G[x][i]; 20 ret += rdfs(to); 21 } 22 return ret; 23 } 24 25 int main() { 26 int T; 27 scanf("%d", &T); 28 while(T--) { 29 int N; 30 scanf("%d", &N); 31 for(int i = 1; i <= N; ++i) G[i].clear(); 32 for(int i = 1; i <= N; ++i) { 33 int x; 34 char s[11]; 35 scanf("%d %s", &x, s + 1); 36 if(s[1] == 'w') a[i] = x; 37 else { 38 a[i] = 0; 39 G[x].push_back(i); 40 } 41 } 42 int ans = 0; 43 for(int i = 1; i <= N; ++i) { 44 if(a[i] == 0) continue; 45 if(dfs(i, a[i])) ans += rdfs(a[i]); 46 } 47 printf("0 %d\n", ans); 48 } 49 return 0; 50 }
1010 Chopping hands
1011 sacul
1012 Pinball
梦回糕烤
1 #include<bits/stdc++.h> 2 using namespace std; 3 long long T,i,j,k,s; 4 double a,b,vx,vy,x,y,g=9.8,ans,temp,t,x2,y2,angle1,angle2,vv; 5 int main() 6 { 7 scanf("%lld",&T); 8 while (T--) 9 { 10 scanf("%lf%lf%lf%lf",&a,&b,&x,&y); 11 angle1=atan(b/a); 12 vx=vy=0; 13 s=0; 14 while (true) 15 { 16 t=a*vy+b*vx; 17 temp=t+sqrt(t*t+2*a*g*(a*y+b*x)); 18 temp=temp/(a*g); 19 x2=x+vx*temp;y2=y+vy*temp-0.5*g*temp*temp; 20 if (x2>=0) break; else s++; 21 vy=vy-temp*g; 22 angle2=atan(-vx/vy); 23 temp=acos(-1.0)*0.5-2*angle1-angle2; 24 vv=sqrt(vx*vx+vy*vy); 25 vx=vv*cos(temp); 26 vy=vv*sin(temp); 27 x=x2;y=y2; 28 } 29 printf("%lld\n",s); 30 } 31 }