Just finished the day thinking of the weak, the evening came thinking three questions ...
T1:https://www.luogu.org/problem/T92604
The law did not find out, 35pts roll rough play table
Can be shown (not I), p = a ^ 3 + 3a + 1
When a = 871, p> 2e9, therefore enumerated a, and sqrt (L) determination whether p is a prime number can be
T2:https://www.luogu.org/problem/T92605
Thought for a moment on the test, that sum is not good maintenance, so it is violent ...
Title to the y = -1 or 1, ensures that, for a number of modifications, it will only affect around one of the sum
Practice: Statistical SUM [i]: number of values <= i and, [i] num, = number of values of i and
Then, for a number, it can not be deleted, if and only if the num [i]! = 0 && sum [i]! = I
Remember the answer to the above is ok [i], the sequence segment tree maintenance, so we get a weight tree line, the value of 0/1
For inquiries, asking the equivalent of 1-x 1 rightmost position, easy to maintain
For the modification, consider several cases on the line
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<climits> #include<map> #include<queue> #include<cmath> using namespace std; #define O(x) cout << #x << " " << x << endl; #define B cout << "breakpoint" << endl; #define clr(a) memset(a,0,sizeof(a)); inline int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { (ans *= 10) += ch - '0'; ch = getchar(); } return ans * op; } const int maxn = 5e5 + 5; int a[maxn],n,m,tp[maxn]; int num[maxn],sum[maxn]; bool ok[maxn]; struct node { int sum,rm; }; struct seg_tr { node tr[maxn << 2]; #define ls i << 1 #define rs i << 1 | 1 inline node up(node i,node l,node r) { i.sum = l.sum + r.sum; if(r.rm) i.rm = r.rm; else i.rm = l.rm; return i; } void build(int i,int l,int r) { if(l == r) { if(ok[l]) tr[i] = (node){1,l}; else tr[i] = (node){0,0}; return; } int mid = l + r >> 1; build(ls,l,mid); build(rs,mid + 1,r); tr[i] = up(tr[i],tr[ls],tr[rs]); } void change(int i,int l,int r,int x,int d) { if(l == r) { tr[i].sum = d; if(d) tr[i].rm = l; else tr[i].rm = 0; return; } int mid = l + r >> 1; if(x <= mid) change(ls,l,mid,x,d); else change(rs,mid + 1,r,x,d); tr[i] = up(tr[i],tr[ls],tr[rs]); } node query(int i,int l,int r,int ql,int qr) { if(l == ql && r == qr) return tr[i]; int mid = l + r >> 1; if(qr <= mid) return query(ls,l,mid,ql,qr); else if(ql > mid) return query(rs,mid + 1,r,ql,qr); else { node tr1 = query(ls,l,mid,ql,mid),tr2 = query(rs,mid + 1,r,mid + 1,qr); node res = up(res,tr1,tr2); return res; } } }T; int main() { freopen("seq.in","r",stdin); freopen("seq.out","w",stdout); n = read(),m = read(); for(int i = 1;i <= n;i++) a[i] = read(),num[a[i]]++; for(int i = 1;i <= n;i++) { sum[i] = sum[i - 1] + num[i]; if(sum[i] != i && num[i]) ok[i] = 1; } //for(int i = 1;i <= n;i++) printf("%d ",ok[i]); //cout << endl; T.build(1,1,n); while(m--) { int op = read(); if(op == 1) { int x = read(); node ans = T.query(1,1,n,1,x); if(!ans.sum) { printf("0\n"); } else printf("%d\n",sum[ans.rm]); } else { int x = read(),y = read(); int p = a[x]; a[x] += y; if(y == -1) { sum[p - 1]++; if(sum[p] - sum[p - 1] == 0) T.change(1,1,n,p,0); if(sum[p - 1] == p - 1) T.change(1,1,n,p - 1,0); else T.change(1,1,n,p - 1,1); } else { sum[p]--; if(sum[p] - sum[p - 1] == 0) T.change(1,1,n,p,0); else { if(sum[p] == p) T.change(1,1,n,p,0); else T.change(1,1,n,p,1); } if(sum[p + 1] == p + 1) T.change(1,1,n,p + 1,0); else T.change(1,1,n,p + 1,1); } } } } /* 6 7 2 3 4 6 6 6 1 6 2 4 -1 2 4 -1 1 6 1 4 2 2 -1 1 6 */
T3:https://www.luogu.org/problem/T92606
When the examination questions to the net to do this, the result tree dp badly written, a look at this complexity does not explode? So give up
Initial idea: f [u] [i] [j]: u and u subtree, an i-th distribution, number, j up to cover a number of points 2
So u first enumeration assignments, then dp subtree v, v and then give distribution pumps do dp, during the temporary array record
The second question on the half, when assigned to u pump the distribution plan can be legitimate
Thus O (T * n * 200 ^ 3 * logai), GG
And then looked away suddenly realized standard
In dealing with u, we can first deal with v, f array update
After u all sub-trees have been processed, and finally give u distribution pumps
Plus temporary array, is also very good writing
getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { (ans *= 10) += ch - '0'; ch = getchar(); } return ans * op; } const int maxn = 25; const int M = 55; struct egde { int to,next; }e[maxn << 1]; int fir[maxn],alloc; void adde(int u,int v) { e[++alloc].next = fir[u],fir[u] = alloc,e[alloc].to = v; swap(u,v); e[++alloc].next = fir[u],fir[u] = alloc,e[alloc].to = v; } int n,a[maxn],s1,s2,p1,p2;//p1 > p2 int f[25][M][M],tmp[M][M]; int mid,ans; void dp(int u,int fa) { for(int i = fir[u];i;i = e[i].next) { int v = e[i].to; if(v == fa) continue; dp(v,u); clr(tmp); for(int i = 0;i <= s1;i++) for(int j = 0;j <= s2;j++) for(int x = 0;x <= i;x++) for(int y = 0;y <= j;y++) tmp[i][j] = max(tmp[i][j],f[u][i - x][j - y] + f[v][x][y]); for(int i = 0;i <= s1;i++) for(int j = 0;j <= s2;j++) f[u][i][j] = tmp[i][j]; } clr(tmp); for(int i = 0;i <= s1;i++) for(int j = 0;j <= s2;j++) for(int x = 0;x <= i;x++) for(int y = 0;y <= j;y++) if(x * p1 + y * p2 >= a[u] && x * p1 + y * p2 - a[u] <= mid) tmp[i][j] = max(tmp[i][j],f[u][i - x][j - y] + 1); for(int i = 0;i <= s1;i++) for(int j = 0;j <= s2;j++) f[u][i][j] = tmp[i][j]; } bool solve() { clr(f); dp(1,0); int res = 0; for(int i = 0;i <= s1;i++) for(int j = 0;j <= s2;j++) res = max(res,f[1][i][j]); return res == ans; } main() { freopen("system.in","r",stdin); freopen("system.out","w",stdout); int t = read(); while(t--) { int n = read(); clr(fir); alloc = 0; for(int i = 1;i <= n;i++) a[i] = read(); for(int i = 1;i < n;i++) { int u = read(),v = read(); adde(u,v); } s1 = read(),s2 = read(),p1 = read(),p2 = read(); mid = 1000000000; clr(f); dp(1,0); ans = 0; for(int i = 0;i <= s1;i++) for(int j = 0;j <= s2;j++) ans = max(ans,f[1][i][j]); printf("%lld ",ans); int l = 0,r = 1000000000,prel = 0,prer = 0; int res = 0; while(l < r) { mid = (l + r) >> 1ll; if(solve()) r = mid,res = mid; else l = mid + 1; if(l == prel && r == prer) res = r,r--; prel = l,prer = r; } printf("%lld\n",res); } } /* 1 4 5 30 20 20 1 2 1 3 3 4 4 1 10 15 */