A:有字符串A和B,若A和B匹配,那么字符集存在一个单射,使得F(A)=B。现在给出长度为n的序列和长度为m的序列,问第一个序列中有多少子串与第二个序列匹配。
回想kmp的过程,事实上,只要“等于号”满足传递性就可以进行匹配。
看代码就知道了。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1E6+5; 4 int n,m,a[maxn],b[maxn],f[maxn],last[maxn],lastA[maxn],bucket[maxn],ans[maxn]; 5 inline int read() 6 { 7 char ch=getchar(); 8 while(!isdigit(ch))ch=getchar(); 9 int sum=ch-'0';ch=getchar(); 10 while(isdigit(ch)){sum=sum*10+ch-'0';ch=getchar();} 11 return sum; 12 } 13 int G[55]; 14 inline void write(int x,const char&ch) 15 { 16 int g=0; 17 do{G[++g]=x%10;x/=10;}while(x); 18 for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar(ch); 19 } 20 inline bool match(int x,int y) 21 { 22 if(last[y]>=x||last[y]==0) 23 { 24 if(last[x]==0) 25 return true; 26 return false; 27 } 28 else 29 { 30 if(b[x-last[y]]==b[x]) 31 return true; 32 return false; 33 } 34 } 35 inline bool matchA(int x,int y) 36 { 37 if(lastA[y]>=x||lastA[y]==0) 38 { 39 if(last[x]==0) 40 return true; 41 return false; 42 } 43 else 44 { 45 if(b[x-lastA[y]]==b[x]) 46 return true; 47 return false; 48 } 49 } 50 inline void solve() 51 { 52 memset(f,0,sizeof(f)); 53 memset(last,0,sizeof(last)); 54 memset(lastA,0,sizeof(lastA)); 55 memset(bucket,0,sizeof(bucket)); 56 n=read(),m=read(); 57 for(int i=1;i<=n;++i) 58 { 59 a[i]=read(); 60 lastA[i]=bucket[a[i]]; 61 bucket[a[i]]=i; 62 } 63 memset(bucket,0,sizeof(bucket)); 64 for(int i=1;i<=m;++i) 65 { 66 b[i]=read(); 67 last[i]=bucket[b[i]]; 68 bucket[b[i]]=i; 69 } 70 for(int i=1;i<=m;++i) 71 if(last[i]) 72 last[i]=i-last[i]; 73 for(int i=1;i<=n;++i) 74 if(lastA[i]) 75 lastA[i]=i-lastA[i]; 76 int pos=0; 77 for(int i=2;i<=m;++i) 78 { 79 while(pos&&!match(pos+1,i)) 80 pos=f[pos]; 81 if(match(pos+1,i)) 82 ++pos; 83 f[i]=pos; 84 } 85 int tot=0; 86 pos=0; 87 for(int i=1;i<=n;++i) 88 { 89 while(pos&&!matchA(pos+1,i)) 90 pos=f[pos]; 91 if(matchA(pos+1,i)) 92 ++pos; 93 if(pos==m) 94 { 95 ans[++tot]=i-m+1; 96 pos=f[pos]; 97 } 98 } 99 write(tot,'\n'); 100 for(int i=1;i<=tot;++i) 101 write(ans[i],' '); 102 putchar('\n'); 103 } 104 int main() 105 { 106 // freopen("xiz.in","r",stdin); 107 // freopen("xiz.out","w",stdout); 108 ios::sync_with_stdio(false); 109 int T=read(),useless=read(); 110 while(T--) 111 solve(); 112 return 0; 113 }
B:n个同心圆,每个同心圆上选择一个点,问这些点组成的凸包面积最大为多少。n<=8。
一个三角形面积计算可以看成是a*b*sin/2,这里不用叉积,方便拉格朗日数乘,没什么好说的。
可以看csl的。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long double ld; 4 const ld pi=acos(-1); 5 const ld eps=1E-8; 6 int n,m,p[55]; 7 ld ans,a[55],r[55],theta[55]; 8 inline bool cmp(ld x,ld y) 9 { 10 return x>y; 11 } 12 inline ld get(ld lambda) 13 { 14 ld tot=0,sum=0; 15 r[m+1]=r[1]; 16 for(int i=1;i<=m;++i) 17 { 18 theta[i]=acos(lambda/(r[i]*r[i+1])); 19 tot+=theta[i]; 20 } 21 return tot; 22 } 23 inline void solve() 24 { 25 for(int i=1;i<=m;++i) 26 r[i]=a[p[i]]; 27 ld L=-a[n]*a[n-1],R=a[n]*a[n-1],mid; 28 while(abs(L-R)>eps) 29 { 30 mid=(L+R)/2; 31 if(get(mid)>=2*pi) 32 L=mid; 33 else 34 R=mid; 35 } 36 if(abs(get(mid)-2*pi)<=0.000001) 37 { 38 r[m+1]=r[1]; 39 ld sum=0; 40 for(int i=1;i<=m;++i) 41 sum+=r[i]*r[i+1]*sin(theta[i]); 42 ans=max(ans,sum); 43 } 44 } 45 int main() 46 { 47 // freopen("yja.in","r",stdin); 48 // freopen("yja.out","w",stdout); 49 ios::sync_with_stdio(false); 50 cin>>n; 51 for(int i=1;i<=n;++i) 52 cin>>a[i]; 53 sort(a+1,a+n+1,cmp); 54 for(m=3;m<=n;++m) 55 { 56 for(int i=1;i<=m;++i) 57 p[i]=i; 58 do 59 { 60 solve(); 61 }while(next_permutation(p+1,p+m+1)); 62 } 63 cout<<fixed<<setprecision(8)<<ans/2<<endl; 64 return 0; 65 } 66 /* 67 276500.1521568 68 8 69 100 200 300 400 500 600 700 1000 70 8 71 1 100 300 400 500 600 700 1000 72 8 73 1 1 1 1 1000 1000 1000 1000 74 */
C:区间排序(有升序,也有降序),区间求和。
这是std的代码,不知为何有这么长。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <cctype> 6 #include <climits> 7 #include <cassert> 8 #include <ctime> 9 #include <iostream> 10 #include <fstream> 11 #include <algorithm> 12 #include <functional> 13 #include <string> 14 15 #define x first 16 #define y second 17 #define MP std::make_pair 18 #define VAL(x) #x " = " << x << " " 19 #define DEBUG(...) fprintf(stderr, __VA_ARGS__) 20 #ifdef __linux__ 21 #define getchar getchar_unlocked 22 #define putchar putchar_unlocked 23 #endif 24 25 typedef long long LL; 26 typedef std::pair<int, int> Pii; 27 28 const int oo = 0x3f3f3f3f; 29 30 template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, true : false; } 31 template<typename T> inline bool chkmin(T &a, T b) { return a > b ? a = b, true : false; } 32 std::string procStatus() 33 { 34 std::ifstream t("/proc/self/status"); 35 return std::string(std::istreambuf_iterator<char>(t), std::istreambuf_iterator<char>()); 36 } 37 template<typename T> T read(T &x) 38 { 39 int f = 1; 40 char ch = getchar(); 41 for (; !isdigit(ch); ch = getchar()) 42 if (ch == '-') 43 f = -1; 44 for (x = 0; isdigit(ch); ch = getchar()) 45 x = 10 * x + ch - '0'; 46 return x *= f; 47 } 48 template<typename T> void write(T x) 49 { 50 if (x == 0) { 51 putchar('0'); 52 return; 53 } 54 if (x < 0) { 55 putchar('-'); 56 x = -x; 57 } 58 static char s[20]; 59 int top = 0; 60 for (; x; x /= 10) 61 s[++top] = x % 10 + '0'; 62 while (top) 63 putchar(s[top--]); 64 } 65 66 67 typedef long double LD; 68 69 const int MAXN = 2e5 + 5, MAXM = 2e5 + 5; 70 71 int N, M; 72 int A0[MAXN]; 73 LD A[MAXN]; 74 int id[MAXN], begin[MAXN], end[MAXN]; 75 bool incp[MAXN]; 76 std::pair<LD, int> hash[MAXN]; 77 78 namespace GlobalSEGT 79 { 80 81 const int SIZE = MAXN << 2; 82 83 int min[SIZE], max[SIZE]; 84 LD sum[SIZE]; 85 int modt[SIZE]; 86 bool modp[SIZE]; 87 bool cleart[SIZE]; 88 int L, R; 89 int Xmin, Xmax; 90 LD Xsum; 91 92 #define LC (u << 1) 93 #define RC (u << 1 | 1) 94 95 inline void tagClear(int u) 96 { 97 cleart[u] = true; 98 sum[u] = 0; 99 } 100 101 inline void tagMod(int u, int x) 102 { 103 modp[u] = true; 104 min[u] = max[u] = modt[u] = x; 105 } 106 107 inline void pushdown(int u) 108 { 109 if (cleart[u]) { 110 tagClear(LC); 111 tagClear(RC); 112 cleart[u] = false; 113 } 114 if (modp[u]) { 115 tagMod(LC, modt[u]); 116 tagMod(RC, modt[u]); 117 modp[u] = false; 118 } 119 } 120 121 inline void pushup(int u) 122 { 123 min[u] = std::min(min[LC], min[RC]); 124 max[u] = std::max(max[LC], max[RC]); 125 sum[u] = sum[LC] + sum[RC]; 126 } 127 128 void _update(int u, int l = 1, int r = N) 129 { 130 if (l == r) { 131 sum[u] = Xsum; 132 return; 133 } 134 pushdown(u); 135 int mid = (l + r) >> 1; 136 if (L <= mid) 137 _update(LC, l, mid); 138 else 139 _update(RC, mid + 1, r); 140 pushup(u); 141 } 142 143 void _modify(int u, int l = 1, int r = N) 144 { 145 if (L <= l && r <= R) { 146 tagMod(u, Xmin); 147 return; 148 } 149 pushdown(u); 150 int mid = (l + r) >> 1; 151 if (L <= mid) 152 _modify(LC, l, mid); 153 if (mid < R) 154 _modify(RC, mid + 1, r); 155 pushup(u); 156 } 157 158 void _clear(int u, int l = 1, int r = N) 159 { 160 if (L <= l && r <= R) { 161 tagClear(u); 162 return; 163 } 164 pushdown(u); 165 int mid = (l + r) >> 1; 166 if (L <= mid) 167 _clear(LC, l, mid); 168 if (mid < R) 169 _clear(RC, mid + 1, r); 170 pushup(u); 171 } 172 173 void _query(int u, int l = 1, int r = N) 174 { 175 if (L <= l && r <= R) { 176 chkmin(Xmin, min[u]); 177 chkmax(Xmax, max[u]); 178 Xsum += sum[u]; 179 return; 180 } 181 pushdown(u); 182 int mid = (l + r) >> 1; 183 if (L <= mid) 184 _query(LC, l, mid); 185 if (mid < R) 186 _query(RC, mid + 1, r); 187 } 188 189 inline void update(int p, LD sm) 190 { 191 L = p; 192 Xsum = sm; 193 _update(1); 194 } 195 196 inline void modify(int l, int r, int x) 197 { 198 L = l; R = r; 199 Xmin = x; 200 _modify(1); 201 } 202 203 inline void clear(int l, int r) 204 { 205 L = l; R = r; 206 _clear(1); 207 } 208 209 inline void query(int l, int r, int &mn, int &mx, LD &sm) 210 { 211 L = l; R = r; 212 Xmin = +oo; Xmax = -oo; Xsum = 0; 213 _query(1); 214 mn = Xmin; mx = Xmax; sm = Xsum; 215 } 216 217 } 218 219 namespace SEGT 220 { 221 222 const int SIZE = 1e7 + 5; 223 224 int size, lc[SIZE], rc[SIZE]; 225 int cnt[SIZE]; 226 LD sum[SIZE]; 227 228 inline void pushup(int u) 229 { 230 cnt[u] = cnt[lc[u]] + cnt[rc[u]]; 231 sum[u] = sum[lc[u]] + sum[rc[u]]; 232 } 233 234 void insert(int &u, int p, int l = 1, int r = N) 235 { 236 if (u == 0) 237 u = ++size; 238 if (l == r) { 239 ++cnt[u]; 240 sum[u] += hash[l].x; 241 return; 242 } 243 int mid = (l + r) >> 1; 244 if (p <= mid) 245 insert(lc[u], p, l, mid); 246 else 247 insert(rc[u], p, mid + 1, r); 248 pushup(u); 249 } 250 251 LD query(int u, int lim, int l = 1, int r = N) 252 { 253 if (u == 0 || lim <= 0) 254 return 0; 255 if (cnt[u] <= lim) 256 return sum[u]; 257 int mid = (l + r) >> 1; 258 return query(lc[u], lim, l, mid) + query(rc[u], lim - cnt[lc[u]], mid + 1, r); 259 } 260 261 void merge(int &u, int v, int l = 1, int r = N) 262 { 263 if (v == 0) 264 return; 265 if (u == 0) { 266 u = v; 267 return; 268 } 269 int mid = (l + r) >> 1; 270 merge(lc[u], lc[v], l, mid); 271 merge(rc[u], rc[v], mid + 1, r); 272 pushup(u); 273 } 274 275 void split(int &u, int &v, int kth, int l = 1, int r = N) 276 { 277 if (v == 0) 278 v = ++size; 279 lc[v] = rc[v] = 0; 280 int mid = (l + r) >> 1; 281 if (cnt[lc[u]] >= kth) { 282 rc[v] = rc[u]; 283 rc[u] = 0; 284 if (cnt[lc[u]] > kth) 285 split(lc[u], lc[v], kth, l, mid); 286 } else 287 split(rc[u], rc[v], kth - cnt[lc[u]], mid + 1, r); 288 pushup(u); 289 pushup(v); 290 } 291 292 } 293 294 void input() 295 { 296 read(N); read(M); 297 for (int i = 1; i <= N; ++i) { 298 read(A0[i]); 299 } 300 } 301 302 void solve() 303 { 304 LD bound[15]; 305 306 for (int i = 1; i < 10; ++i) { 307 bound[i] = log10((LD)i); 308 } 309 310 for (int i = 1; i <= N; ++i) { 311 A[i] = log10((LD)A0[i]); 312 hash[i] = MP(A[i], i); 313 } 314 std::sort(hash + 1, hash + N + 1); 315 for (int i = 1; i <= N; ++i) { 316 id[hash[i].y] = i; 317 } 318 319 static int root[MAXN]; 320 321 for (int i = 1; i <= N; ++i) { 322 root[i] = ++SEGT::size; 323 SEGT::insert(root[i], id[i]); 324 begin[i] = end[i] = i; 325 GlobalSEGT::modify(i, i, i); 326 GlobalSEGT::update(i, A[i]); 327 incp[i] = true; 328 } 329 330 while (M--) { 331 int type; 332 int l, r; 333 read(type); read(l); read(r); 334 335 if (type == 1) { 336 int flag; 337 read(flag); 338 339 int lp, rp; 340 LD sum; 341 GlobalSEGT::query(l, r, lp, rp, sum); 342 if (begin[lp] < l) { 343 int s = begin[lp]; 344 if (incp[s]) 345 SEGT::split(root[s], root[l], l - s); 346 else { 347 SEGT::split(root[s], root[l], lp + 1 - l); 348 std::swap(root[s], root[l]); 349 } 350 begin[lp] = l; 351 incp[l] = incp[s]; 352 begin[l - 1] = s; 353 end[s] = l - 1; 354 GlobalSEGT::modify(s, l - 1, l - 1); 355 GlobalSEGT::clear(s, l - 1); 356 GlobalSEGT::update(s, SEGT::sum[root[s]]); 357 } 358 if (rp > r) { 359 int t = begin[rp]; 360 if (incp[t]) 361 SEGT::split(root[t], root[r + 1], r + 1 - t); 362 else { 363 SEGT::split(root[t], root[r + 1], rp - r); 364 std::swap(root[t], root[r + 1]); 365 } 366 begin[rp] = r + 1; 367 end[r + 1] = rp; 368 incp[r + 1] = incp[t]; 369 GlobalSEGT::modify(r + 1, rp, rp); 370 GlobalSEGT::clear(r + 1, rp); 371 GlobalSEGT::update(r + 1, SEGT::sum[root[r + 1]]); 372 } 373 for (int j = lp + 1; j <= r; j = end[j] + 1) { 374 SEGT::merge(root[l], root[j]); 375 } 376 377 begin[r] = l; 378 end[l] = r; 379 incp[l] = flag; 380 GlobalSEGT::modify(l, r, r); 381 GlobalSEGT::clear(l, r); 382 GlobalSEGT::update(l, SEGT::sum[root[l]]); 383 } else { 384 int lp, rp; 385 LD x; 386 GlobalSEGT::query(l, r, lp, rp, x); 387 if (begin[lp] < l) { 388 int s = begin[lp]; 389 x += incp[s] ? SEGT::sum[root[s]] - SEGT::query(root[s], l - s) : SEGT::query(root[s], lp + 1 - l); 390 } 391 if (rp > r) { 392 int t = begin[rp]; 393 x -= incp[t] ? SEGT::sum[root[t]] - SEGT::query(root[t], r + 1 - t) : SEGT::query(root[t], rp - r); 394 } 395 396 x -= floor(x); 397 int ans = std::upper_bound(bound + 1, bound + 10, x) - bound - 1; 398 write(ans); putchar('\n'); 399 } 400 } 401 } 402 403 int main() 404 { 405 // freopen("zkb.in", "r", stdin); 406 // freopen("zkb.out", "w", stdout); 407 408 input(); 409 solve(); 410 411 return 0; 412 }