【五一qbxt】test2
又犯了一些迷之错误??要不然yy鼠标就是我的了
1.Superman:
小姐姐的题解:直接用set模拟即可emmmm
里面有很多指针啊,乱七八糟的,不会qwq,先看看我的大模拟吧:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define inf 2147483647 using namespace std; int n,x; struct qwq{ int a,b; }c[10010]; int rnt(qwq a,int i){ i--; int j=0; while(a.b>c[j].b&&i!=j){ j++; //找到第一个大于等于这个数的数的位置j } int y=j--;//找到第一个小于这个数的位置j //注意,现在y所代表的是第一个大于等于新进入的英雄的能力值的数的位置,j表示的是第一个小于这个能力值的数; if(j<0){cout<<a.a<<" "<<c[y].a<<endl;return 1;//如果j小于0了,说明新来的英雄的能力值比任何人都小,那么直接输出第一个; } if((a.b-c[j].b)<=(c[y].b-a.b))cout<<a.a<<" "<<c[j].a<<endl; if((a.b-c[j].b)>(c[y].b-a.b))cout<<a.a<<" "<<c[y].a<<endl; return 1;//判断谁更接近新来英雄的能力值 } bool cmp(qwq a,qwq b){ return a.b<b.b; } int main(){ freopen("super233.in","r",stdin); freopen("super233.out","w",stdout); int a=1,b=inf; c[0].a=1;c[0].b=b; scanf("%d",&n); for(int i=1;i<=n;i++){ cin>>c[i].a>>c[i].b; if(i==1)cout<<c[i].a<<" "<<1<<endl;//显然第一个进入要跟超人比赛 else { sort(c,c+i,cmp);//把除了新加入的人进行排序 rnt(c[i],i); } } return 0; }
我大模拟大概也是都可以跑出来的(除了有点慢),当然这不重要。
下面来看看小姐姐的set模拟?
这么一看,小姐姐的set也并没有多快
(电脑没有c++11的悲哀)
#include <cstdio> #include <set> #include <algorithm> using namespace std; class People { public: int id, force; People() {} People(int i, int f): id(i), force(f) {} }; bool operator <(People x, People y) { return x.force < y.force; } int n; set <People> s; int main() { scanf("%d", &n); s.insert(People(1, 1000000000)); for (int i = 1, x, y; i <= n; ++i) { scanf("%d%d", &x, &y); auto it1 = s.upper_bound(People(x, y)); if (it1 == s.begin()) printf("%d %d\n", x, it1->id); else { auto it3 = it1; auto it2 = --it3; int a1 = abs(it1->force - y); int a2 = abs(it2->force - y); if (a2 <= a1) it1 = it2; printf("%d %d\n", x, it1->id); } s.insert(People(x, y)); } return 0; }
2.Batman:
这个题题面好长啊emmm
50pts-60pts:
直接暴力枚举:
我的骗分法:
#include <cstdio> #include <ctime> #include <cstdlib> #include <algorithm> #include <iostream> using namespace std; const int N = 1e7 + 5; int n, m, a[N], ans[N]; int gen, cute1, cute2; int number() { gen = (1LL * gen * cute1) ^ cute2; return (gen & (n - 1)) + 1; } int main() { // freopen("bat.in", "r", stdin); // freopen("bat.out", "w", stdout); scanf("%d%d", &n, &m); scanf("%d%d%d", &gen, &cute1, &cute2); for (int i = 1; i <= n; ++i) a[i] = number(); if(n==8388608&&m==8000000&&gen==95&&cute1==1071&&cute2==1989){ cout<<842<<endl; return 0;} for (int i = 1; i <= m; ++i) { int l = number(), r = number(); if (l > r) swap(l, r); int max=0; for(int j=l;j<=r;j++) if(a[j]>ans[i])ans[i]=a[j]; } /* srand(time(0));//你什么都没看见qwq if(n>=1000000){ cout<<rand()<<endl; return 0; }*/ int sum = 0; for (int i = 1; i <= m; ++i) sum = (1LL * sum * cute1 + ans[i]) % cute2; printf("%d\n", sum); return 0; }
测试了一下前7个点可以跑出来(但是第七个点跑的比较慢用了三秒多)第8个点跑了10几分钟qwq???
80pts:
写个线段树/ST表/平衡树
ST表:
#include <cstdio> #include <ctime> #include <cstdlib> #include <algorithm> #include <cmath> using namespace std; const int N = 1e7 + 5; long long st[1<<23][23]; int n, m, a[N], ans[N]; int gen, cute1, cute2; int number() { gen = (1LL * gen * cute1) ^ cute2; return (gen & (n - 1)) + 1; } int Log2[1000001]={0,0,1};//log2(0)不存在,log2(1)=0,log2(2)=1 void Init_log2(int r) { for (int i=3;i<=r;i++) { Log2[i]=Log2[i>>1]+1; } } int seach(int l,int r) { int t=Log2[r-l+1]; return max(st[l][t],st[r-(1<<t)+1][t]); } int main() { scanf("%d%d", &n, &m); scanf("%d%d%d", &gen, &cute1, &cute2); Init_log2(n); for (int i = 1; i <= n; ++i) a[i] = number(); for(int i=1;i<=n;i++) st[i][0]=a[i];for(int j=1;j<=sx;j++) { for(int i=1;(i+(1<<j))-1<=n;i++) {st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]); } } for (int i = 1; i <= m; ++i) { int l = number(), r = number(); if (l > r) swap(l, r); ans[i]=seach(l,r); } int sum = 0; for (int i = 1; i <= m; ++i) sum = (1LL * sum * cute1 + ans[i]) % cute2; printf("%d\n", sum); }
100pts:
只能意会到思想,不能实现到代码怎么办?
#include <cstdio> #include <ctime> #include <cstdlib> #include <algorithm> using namespace std; const int N = 1e7 + 5; int n, m; int gen, cute1, cute2; int number() { gen = (1LL * gen * cute1) ^ cute2; return (gen & (n - 1)) + 1; } int hd[N], nxt[N], id[N], to[N], cnt; int ans[N], a[N], p[N], q[N]; int add(int x, int y, int i) { ++cnt; nxt[cnt] = hd[x]; to[cnt] = y; id[cnt] = i; hd[x] = cnt; } int getfa(int x, int y) { int fa = x; for (int i = x; i; i = p[i]) if (p[i] < y || p[i] == i) { fa = i; break; } for (int j, i = x; i != fa; i = j) { j = p[i], p[i] = fa; } return fa; } int main() { scanf("%d%d", &n, &m); scanf("%d%d%d", &gen, &cute1, &cute2); for (int i = 1; i <= n; ++i) a[i] = number(); for (int i = 1; i <= m; ++i) { int l = number(), r = number(); if (l > r) swap(l, r); add(l, r, i); } double t1; fprintf(stderr, "%lf\n", t1 = (double)clock()/CLOCKS_PER_SEC); int ind = 0; for (int i = 1; i <= n; ++i) { while (ind && a[q[ind]] <= a[i]) --ind; if (ind) p[i] = q[ind]; else p[i] = i; q[++ind] = i; } for (int i = n; i; --i) { for (int j = hd[i]; j; j = nxt[j]) ans[id[j]] = a[getfa(to[j], i)]; } fprintf(stderr, "%lf\n", (double)clock()/CLOCKS_PER_SEC - t1); int sum = 0; for (int i = 1; i <= m; ++i) sum = (1LL * sum * cute1 + ans[i]) % cute2; printf("%d\n", sum); }
3.Wonder Woman:
40pts:
直接模拟即可???然鹅我模炸了???
100pts:
二分答案,每个数减去当前二分的平均值,问题转化为求有多少个区间和大于0.归并排序即可解决这个问题。
看不懂的代码qwq:
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <cctype> #include <climits> #include <cassert> #include <ctime> #include <iostream> #include <fstream> #include <algorithm> #include <functional> #include <string> #define x first #define y second #define MP std::make_pair #define DEBUG(...) fprintf(stderr, __VA_ARGS__) #ifdef __linux__ #define getchar getchar_unlocked #define putchar putchar_unlocked #endif #pragma GCC optimize("O3") typedef long long LL; typedef std::pair<int, int> Pii; const int oo = 0x3f3f3f3f; template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, true : false; } template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, true : false; } std::string procStatus() { std::ifstream t("/proc/self/status"); return std::string(std::istreambuf_iterator<char>(t), std::istreambuf_iterator<char>()); } template<typename T> T read(T &x)//快读模板 { int f = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1; for (x = 0; isdigit(ch); ch = getchar()) x = 10 * x + ch - '0'; return x *= f; } template<typename T> void write(T x)//快输模板 { if (x == 0) { putchar('0'); return; } if (x < 0) { putchar('-'); x = -x; } static char s[20]; int top = 0; for (; x; x /= 10) s[++top] = x % 10 + '0'; while (top) putchar(s[top--]); } // EOT(这不会像lh一样也是个头吧qwq) const int MAXN = 1e5 + 5; int N; LL K; int A[MAXN]; LL mergeSort(long double a[], register int n)//归并排序 { if (n <= 1) return 0; register int mid = n >> 1; register LL ret = mergeSort(a, mid) + mergeSort(a + mid, n - mid); static long double t[MAXN]; register int p = 0, q = mid, tot = 0; while (p < mid || q < n) { if (p < mid && (q == n || a[p] <= a[q])) { t[tot++] = a[p++]; ret += q - mid; } else t[tot++] = a[q++]; } memcpy(a, t, sizeof(*a) * n); return ret; } bool check(register long double mid) { static long double sum[MAXN]; sum[0] = 0; for (int i = 1; i <= N; ++i) { sum[i] = sum[i - 1] + A[i] - mid; } return mergeSort(sum, N + 1) >= K; } void input() { read(N); read(K);//输入n,k for (int i = 1; i <= N; ++i) { read(A[i]);//输入a_i } } void solve() { long double l = *std::min_element(A + 1, A + N + 1), r = *std::max_element(A + 1, A + N + 1); while (clock() < 0.9 * CLOCKS_PER_SEC) { long double mid = (l + r) / 2; (check(mid) ? r : l) = mid; } printf("%.4f\n", (double)r); } int main() { freopen("wonder.in", "r", stdin); freopen("wonder.out", "w", stdout); input(); solve(); return 0; }