Today, I blew up again, and worshipped rk1 jarden. Giant Blog
T1: [from new_dtoj 2503: HZ(666666) loves meat(meat)]
Title Description
HZ(666666) finally opened the password box and found that it was only a pile of air-dried meat strips, so he decided to feed the dog.
HZ(666666) has n dogs with m meat strips. He wants to distribute each strip to the dogs and make each dog have at least one strip to eat. Dogs are always greedy. They don't want to see other dogs have more meat strips, otherwise they will be unhappy. The degree of unhappiness of a dog can be expressed as the product of greed and the number of dogs with more meat than it. Now HZ(666666) wants to know a way of allocation that minimizes the unhappiness of dogs.
Title Solution
szm God said this is extended integer division, quickly d her
First of all, we know that the bigger the greed value, the more biscuits, so let's sort them from big to small.
Let f[i][j]f[i][j]f[i][j] f [i] [j] denote the minimum unhappy sum of the first I individuals, divided into J biscuits.
If the meat strip of the first dog is more than 1, the relative order and the total amount of resentment of the first dog are invariable when the j_i meat strips are allocated equally to the first dog.
If the first child has only one biscuit, then enumerate how many children have received a biscuit before.
So we can get the dp formula.
- f[i][j]=f[i][j−i]f[i][j]=f[i][j-i]f[i][j]=f[i][j−i]
- f[i][j]=f[k][j−(i−k)]+∑p=k+1ia[p]f[i][j]=f[k][j-(i-k)]+\sum_{p=k+1}^ia[p]f[i][j]=f[k][j−(i−k)]+∑p=k+1ia[p]
If the output scheme is used, the path can be recorded.
Efficiency O(n2m)O(n^2m)O(n2m)
#include <cstdio> #include <algorithm> using namespace std; int n,m,s[55],f[55][5005],a[55]; struct O{int g,d;}p[55],r[55][5005],h,l; bool C(O x,O y){return x.g>y.g;} int main(){ scanf("%d%d",&n,&m); for (int i=0;i<=n;i++) for (int j=0;j<=m;j++) f[i][j]=1e9; f[0][0]=0;for (int i=1;i<=n;i++) scanf("%d",&p[i].g),p[i].d=i; sort(p+1,p+n+1,C);for (int i=1;i<=n;i++) s[i]=s[i-1]+p[i].g; for (int i=1;i<=n;i++) for (int j=i;j<=m;j++){ f[i][j]=f[i][j-i];r[i][j]=(O){i,j-i}; for (int k=0;k<i;k++){ int t=f[k][j-i+k]+k*(s[i]-s[k]); if (t<f[i][j]) f[i][j]=t,r[i][j]=(O){k,j-i+k}; } } printf("%d\n",f[n][m]);h=(O){n,m}; while(h.g && h.d){ l=r[h.g][h.d]; if (l.g==h.g) for (int i=1;i<=l.g;i++) a[p[i].d]++; else for (int i=l.g+1;i<=h.g;i++) a[p[i].d]++; h=l; } for (int i=1;i<=n;i++) printf("%d%c",a[i],i<n?' ':'\n'); return 0; }
T2: [rideon, leader from new_dtoj who can't stop]
Title Description
No time
Title Solution
The exam room thought of the state, but the transfer was wrong, and then boom was blown up.
What I'm writing is that let f[i] denote the number of steps needed to pass this point for the second time.
So first we're going to come over from i-1, so f[i-1]+1
Then we find that he jumps back to p[i], and since this is something like a prefix sum, we should add an f[i-1]-f[p[i]-1]
Finally, we need to go one step, so we need + 1.
So f[i]=f[i-1]*2+f[p[i]-1]+2
Note the case of special judgment p[i]=i, i.e. f[i]=2
Efficiency O(n)O(n)O(n)O(n)
#include <cstdio> const int N=1e6+5,P=1e9+7; int n,p[N],f[N]; int main(){ scanf("%d",&n);for (int i=1;i<=n;i++) scanf("%d",&p[i]); for (int i=1;i<=n;i++) f[i]=(2ll*f[i-1]+2-f[p[i]-1]+P)%P; return printf("%d\n",f[n]),0; }
T3: [from new_dtoj 3996: Lesson5!(johnny)]
Title Description
No time
Title Solution
Johnny is a famous goose in my English exam and has no idea about it at all.
jarden: I thought of it in my sleep, G
Because it's a DAG, we can run the topology twice to find the longest path f[] f[\] f[], g[] g[\] g[] g [\] g [] from each point and to each point.
Then we put g [] g [\] g [] into a weight segment tree, and then take out an X according to the topological order each time. We take out g[x]g[x]g[x] g [x] and g[x]+f[y]+1g[x]+f[y]+1g[x]+f[y]+1 (y points to x, edge weight is 1).
At this point, we can find that the operation is equivalent to x being deleted, so we can find the maximum subscript in the segment tree. If the value is smaller than the value of ans, that is the answer.
(You can also use other preferred data structures, such as multiset or heap)
Efficiency O(nlogn)O(nlogn)O(nlogn)O(nlogn)
#include <cstdio> #include <cstring> #include <string> #define _(d) while(d(isdigit(c=getchar()))) #define Ls k<<1 #define Rs Ls|1 using namespace std; inline int R(){int x;char c;_(!);x=(c^48);_()x=(x<<3)+(x<<1)+(c^48);return x;} const int N=1e5+5,M=5e5+5; int T,n,m,in[N],ot[N],f[N],g[N],q[N],c,h,ans,id,s[N*4],ax[N*4]; struct O{ int t,head[N],V[M],nex[M]; inline void add(int u,int v){ V[++t]=v;nex[t]=head[u];head[u]=t; } }e1,e2; inline void update(int k,int l,int r,int x,int v){ if (l==r){ s[k]+=v; if (s[k]>0) ax[k]=l; else ax[k]=-1,s[k]=0; return; } int mid=l+r>>1; if (mid>=x) update(Ls,l,mid,x,v); else update(Rs,mid+1,r,x,v); ax[k]=max(ax[Ls],ax[Rs]); } int main(){ for (T=R();T--;){ n=R();m=R();e1.t=e2.t=0;ans=1e9; memset(s,0,sizeof s);memset(ax,0,sizeof ax); for (int i=1;i<=n;i++) e1.head[i]=e2.head[i]=in[i]=ot[i]=g[i]=f[i]=0; for (int x,y,i=1;i<=m;i++) x=R(),y=R(),e1.add(x,y),e2.add(y,x),in[y]++,ot[x]++; c=0;h=1;for (int i=1;i<=n;i++) if (!ot[i]) q[++c]=i; while(h<=c){ for (int i=e2.head[q[h]];i;i=e2.nex[i]){ if (g[e2.V[i]]<g[q[h]]+1) g[e2.V[i]]=g[q[h]]+1; ot[e2.V[i]]--;if (!ot[e2.V[i]]) q[++c]=e2.V[i]; } h++; } c=0;h=1;for (int i=1;i<=n;i++) if (!in[i]) q[++c]=i; while(h<=c){ for (int i=e1.head[q[h]];i;i=e1.nex[i]){ if (f[e1.V[i]]<f[q[h]]+1) f[e1.V[i]]=f[q[h]]+1; in[e1.V[i]]--;if (!in[e1.V[i]]) q[++c]=e1.V[i]; } h++; } for (int i=1;i<=n;i++) update(1,0,n,g[i],1); for (int i=1;i<=n;i++){ update(1,0,n,g[q[i]],-1); for (int j=e2.head[q[i]];j;j=e2.nex[j]) update(1,0,n,g[q[i]]+1+f[e2.V[j]],-1); if (ans>ax[1] || ans==ax[1] && id>q[i]) ans=ax[1],id=q[i]; for (int j=e1.head[q[i]];j;j=e1.nex[j]) update(1,0,n,f[q[i]]+1+g[e1.V[j]],1); update(1,0,n,f[q[i]],1); } printf("%d %d\n",id,ans); } return 0; }