5.28 Exam Revision + Summary

Source: Internet
Author: User
Tags mul

Today is a sad story, all the people who rank higher than I have a first question

And my first question is zero.

But the happy thing is: The first question is not said to be a simple diagram, so the problem is wrong

No matter what, will wrong.

This afternoon broke the net, so this time only to write blog

First question

Because the topic did not give the concept of Eulerian graph, so I do not know what it is talking about, so it exploded zero

Then Eulerian graph is a simple diagram of the existence of the Euler circuit, with the following characteristics:

1. Unicom

2, the degrees are even

Obviously we will wrong see the topic, the number of Eulerian graph * (n (n-1)/2+1) can get the answer

Then it is easy to know that the number of graphs with even numbers of degrees is 2^ ((n-1) * (n-2)/2)

is to consider proposing one of the points, the remaining points of the arbitrary composition, and then for the proposed point and there is only one scheme to make the current graph degrees are even

After the DP using the principle can be used to find out the degree of connectivity is the number of even, the practice is to use the total-non-connected

is not connected to the only need to enumerate 1 the size of the Unicom block can be

Time complexity O (n^2)

#include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include < Algorithm>using namespace Std; typedef long LONG ll;const int maxn=2010;const int mod=1e9+7;int n; LL H[MAXN],G[MAXN],F[MAXN]; LL JC[MAXN],INV[MAXN];    ll Pow_mod (ll V,int p) {ll tmp=1;        while (p) {if (p&1) Tmp=tmp*v%mod;    v=v*v%mod;p>>=1; }return tmp;}    LL C (int n,int m) {return jc[n]*inv[m]%mod*inv[n-m]%mod;} int main () {scanf ("%d", &n);    Jc[0]=1;    for (int i=1;i<=n;++i) Jc[i]=jc[i-1]*i%mod;    Inv[n]=pow_mod (jc[n],mod-2);    for (int i=n-1;i>=0;--i) inv[i]=inv[i+1]* (i+1)%mod;    h[1]=1;f[1]=1;g[1]=0;    for (int i=2;i<=n;++i) H[i]=pow_mod (2LL, (i-1) * (i-2)/2);        for (int i=2;i<=n;++i) {f[i]=h[i];            for (int j=1;j<=i-1;++j) {f[i]=f[i]-c (i-1,j-1) *f[j]%mod*h[i-j]%mod;        if (f[i]<0) F[i]+=mod;    }}f[n]=f[n]+n* (n-1) *pow_mod (2ll,mod-2)%mod*f[n]%mod;    if (f[n]>=mod) F[n]-=mod;   printf ("%lld\n", F[n]); return 0;} 

And then it's easy to see that the formula is a convolution form when it's not connected.

So we can FFT, I am idle bored write a cdq+fft

Since modulus is not very supportive, we have to do 9 DFT each time

Then although the theoretical Complexity O (nlog^2n), but can only run over 20000 of the data Qaq

#include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> #include < algorithm> #include <cmath> #define G 3using namespace Std;const int maxn=400010;typedef long long ll;int n,n,len; const int Mod=1e9+7;const int M=30000;const long double pi=acos ( -1.0); int Jc[maxn],inv[maxn];int H[maxn],f[maxn];int Rev [Maxn],num[22];int a[maxn],b[maxn],c[maxn];int a0[maxn],b0[maxn],a1[maxn],b1[maxn];struct Cpx{long Double r,i;cpx ( Long double R=0,long Double i=0): R (R), I (i) {}}A[MAXN],B[MAXN],C[MAXN];CPX operator + (const CPX &a,const cpx &b) { Return CPX (A.R+B.R,A.I+B.I);} CPX operator-(const CPX &a,const cpx &b) {return CPX (A.R-B.R,A.I-B.I);} CPX operator * (const CPX &a,const cpx &b) {return CPX (A.R*B.R-A.I*B.I,A.R*B.I+A.I*B.R);} void FFT (CPX *a,int n,int type) {for (Int. i=0;i<n;++i) if (I<rev[i]) swap (a[i],a[rev[i]]); for (int k=0; (1<<k) &LT;N;++K) {int m= (1<<k), m2= (m<<1); long double o=2*pi/m2*type;cpx wn (cos (o), sin (o)); for (int i=0;I&LT;N;I+=M2) {CPX W (1,0); for (int j=0;j<m;++j) {CPX x=a[i+j],y=a[i+j+m]*w; A[i+j]=x+y; A[i+j+m]=x-y;w=w*wn;}}} if (type==-1) for (int i=0;i<n;++i) a[i].r/=n;} void Mul (int *a,int *b,int *c) {for (int i=0;i<n;++i) A[I]=CPX (a[i],0), B[I]=CPX (b[i],0); FFT (a,n,1); FFT (b,n,1); for (int i=0;i<n;++i) a[i]=a[i]*b[i]; FFT (A,n,-1), for (int i=0;i<n;++i) c[i]= ((LL) (a[i].r+0.5))%mod;} void Mul_mod (int *a,int *b,int *c) {for (int i=0;i<n;++i) A0[i]=a[i]/m,b0[i]=b[i]/m;mul (A0,B0,A0), for (int i=0;i<n ; ++i) {c[i]=1ll*a0[i]*m%mod*m%mod;a1[i]=a[i]%m;b1[i]=b[i]%m;} Mul (A1,B1,A1); for (int i=0;i<n;++i) {c[i]=c[i]+a1[i];if (c[i]>=mod) c[i]-=mod;a1[i]=a1[i]+a0[i];if (a1[i]>= MoD) a1[i]-=mod;a0[i]=a[i]/m+a[i]%m;b0[i]=b[i]/m+b[i]%m;} Mul (a0,b0,a0); for (int i=0;i<n;++i) {c[i]=c[i]+1ll*m* (a0[i]-a1[i]+mod)%mod;if (C[i]>=mod) C[i]-=mod;} return;} ll Pow_mod (ll V,int p) {ll tmp=1;while (p) {if (p&1) tmp=tmp*v%mod;v=v*v%mod;p>>=1;} return TMP;} void Solve (int l,int R) {if (l==r) Return;int mid= (l+r) >>1; Solve (L,mid); for (n=1,len=0; n< (r-l+1); n<<=1,len++); for (int i=0;i<n;++i) rev[i]=rev[i>>1]>>1| ((i&1) << (len-1)); for (int i=0;i<n;++i) a[i]=b[i]=0;for (int i=l;i<=mid;++i) a[i-l]=1ll*f[i]*inv[i-1] %mod;for (int i=0;i<n;++i) b[i]=h[i];mul_mod (a,b,c); for (int i=mid+1;i<=r;++i) {f[i]=f[i]-1ll*jc[i-1]*c[i-l]% Mod;if (f[i]<0) F[i]+=mod;} Solve (mid+1,r);} int main () {scanf ("%d", &n), jc[0]=1;for (int i=1;i<=n;++i) Jc[i]=1ll*jc[i-1]*i%mod;inv[n]=pow_mod (jc[n],mod-2 ); for (int i=n-1;i>=0;--i) inv[i]=1ll*inv[i+1]* (i+1)%mod;h[1]=1;f[1]=1;for (int i=2;i<=n;++i) {H[i]=pow_mod ( 2LL, (i-1) * (i-2)/2); f[i]=h[i];h[i]=1ll*h[i]*inv[i]%mod;} Solve (1,n); f[n]=f[n]+1ll*n* (n-1) *pow_mod (2ll,mod-2)%mod*f[n]%mod;if (f[n]>=mod) f[n]-=mod;printf ("%d\n", F[n]) ; return 0;}

Second question

Today the second question has been stuck 10 points constant, but also learned some new tricks, also is a blessing in disguise

It is clear that we should consider splitting, and there are two ways of splitting the rule:

The first is the solution, we split the two halves, and then we counted the middle answer.

Maintain a pointer to the left and right, each time to the maximum value of a small extension, so as to ensure that when one side as the maximum value, the other side must be a large expansion interval

And then in the process of the sweep with an array to save the prefix and or suffix and then you can

This is actually a bit of a hassle, because either the prefix maximum or the suffix maximum is monotonous

The end of the corresponding maximal interval is also monotonous, we just need to use the monotony sweep the left and then sweep again to the right.

Pay attention to sweep because the maximum value may be at the same time on the left and the right side, so we sweep the left side of the rule is strictly less than the right side, sweep the right side of the left is less than equal to the

Complexity O (NLOGN)

The second approach is to consider finding the maximum value of the current interval and splitting it into two halves.

We just need to count the middle answer, this time the maximum is fixed, the answer is easy to count

But notice here we theoretically can not sweep all over again, because here is not evenly divided in half, sweep around the limit Complexity O (n^2)

The author later said the data was random qaq and then there was a man in the exam room. (Random Data complexity O (NLOGN))

It's easy to see that we don't have to write division, preprocess each point with a monotone queue to the left and right end of the maximum and then brute force sweep.

Time complexity is the same as the above, although the data can be random, but not very graceful, because it can be jammed

We will find that the problem is converted to the enumeration side to count the number of x on the other side, obviously we can use heuristic thinking, each time we enumerate the shorter side

It is not difficult to find each point is enumerated every time, its interval length is at least/2, so the contribution of each point to the enumeration is O (LOGN)

The time complexity of the enumeration is O (Nlogn), and then the query is apparently done with a persisted segment tree

Total time complexity O (nlog^2n), because such a division may explode stack, so I wrote a BFS in the examination room, the results were stuck 10 points constant

Optimized the Chairman tree on a, as for the Chairman tree optimization if you find that the current interval is 0, you don't have to go down recursively (this is a great optimization for the chairman tree, because think about the chair tree's build process.) )

Later found that the data is random, DFS will not explode stack, change to DFS does not optimize the chairman of the tree can also a, the examination room to think more qaq worry sang ing

But this is more than the complexity of the log, can continue to optimize it? OK!

YMX proposed that you will find the DFS process we do not ask, while the inquiry is split into two prefixes asked to do offline, asking for a maximum of O (NLOGN)

Not difficult to find due to the nature of Dfs, finally get the inquiry sequence naturally ordered, after we go offline O (n) sweep once can O (NLOGN) processing all inquiries

Time complexity O (NLOGN), the actual measurement is not sure where to go

Post the morning code as an optimization souvenir for the Chairman tree:

#include <cstdio> #include <iostream> #include <cstdlib> #include <algorithm> #include < Cstring> #include <queue>using namespace std; typedef long LONG Ll;const int maxn=300010;int n,k,mod;int a[maxn];int vis[1000010],tot=0;int mx[maxn<<2],pos[ Maxn<<2];int Sum[maxn];int CNT=0,RT[MAXN]; LL ans=0;struct seg_tree{int l,r,v;}    t[8000010];struct op{int l,r;    OP (int l=0,int r=0): L (L), R (r) {}};queue<op>q;void read (int &num) {Num=0;char Ch=getchar (); while (ch< '! ')    Ch=getchar (); while (ch>= ' 0 ' &&ch<= ' 9 ') num= (num<<1) + (num<<3) +ch-' 0 ', Ch=getchar ();}    void Build_tree (int o,int l,int R) {if (l==r) {mx[o]=a[l];p Os[o]=l;return;}    int mid= (L+R) >>1;    Build_tree (O<<1,l,mid);    Build_tree (O&LT;&LT;1|1,MID+1,R);    if (mx[o<<1]>mx[o<<1|1]) mx[o]=mx[o<<1],pos[o]=pos[o<<1]; else mx[o]=mx[o<<1|1],pos[o]=pos[o<<1|1];} PAIR&LT;INT,INT&GT;ASK_MX (int o,int l,int r,int x,inT y) {if (l>=x&&r<=y) return Make_pair (Mx[o],pos[o]);    int mid= (L+R) >>1;    if (Y<=mid) return ask_mx (o<<1,l,mid,x,y);    else if (X>mid) return ask_mx (o<<1|1,mid+1,r,x,y);        else{pair<int,int>a=ask_mx (o<<1,l,mid,x,y);        PAIR&LT;INT,INT&GT;B=ASK_MX (O<<1|1,mid+1,r,x,y);        if (A.first>b.first) return A;    return B;    }}void Build (int &o,int l,int R) {o=++cnt;    if (l==r) return;    int mid= (L+R) >>1; Build (T[o].    L,L,MID); Build (T[o]. R,MID+1,R);}    void UPD (int &o,int l,int r,int p) {t[++cnt]=t[o];o=cnt;    if (l==r) {T[o].v++;return;}    int mid= (L+R) >>1; if (p<=mid) UPD (T[o].    L,L,MID,P); else UPD (T[o].    R,MID+1,R,P); T[o].v=t[t[o]. L].v+t[t[o]. R].V;}    int ask (int a,int b,int l,int r,int p) {if (a==b) return 0;    if (l==r) return t[a].v-t[b].v;    int mid= (L+R) >>1; if (P<=mid) return Ask (T[a]. L,T[B].    L,L,MID,P); else return ask (T[a]. R,T[B]. R,MID+1,R,P);}    void BFS () {Q.push (OP (2,n)); while (! Q.empty ()) {OP tmp=q.front ();        Q.pop (); int l=tmp. L,r=tmp.        R        int P=ask_mx (1,1,N,L,R). Second;        if (l<p-1) Q.push (OP (l,p-1));        if (p+1<r) Q.push (OP (p+1,r));        int len=p-l,ren=r-p;            if (ren<len) {int tmp=sum[p]-a[p]+mod;            if (tmp>=mod) Tmp-=mod;            if (Vis[tmp]) Tmp=ask (rt[p-2],rt[l-2],1,tot,vis[tmp]);            else tmp=0;            ans+=tmp;                for (int i=p+1;i<=r;++i) {tmp=sum[i]-a[p]+mod;                if (tmp>=mod) Tmp-=mod;                if (!vis[tmp]) continue;                Tmp=ask (Rt[p-1],rt[l-2],1,tot,vis[tmp]);            ans+=tmp;            }}else{int tmp=sum[p-1]+a[p];            if (tmp>=mod) Tmp-=mod;            if (Vis[tmp]) Tmp=ask (rt[r],rt[p],1,tot,vis[tmp]);            else tmp=0;            ans+=tmp;                for (int i=l-1;i<=p-2;++i) {tmp=sum[i]+a[p];       if (tmp>=mod) Tmp-=mod;         if (!vis[tmp]) continue;                Tmp=ask (Rt[r],rt[p-1],1,tot,vis[tmp]);            ans+=tmp; }}}return;}    int main () {read (n); read (k); n++;mod=k;    for (int i=2;i<=n;++i) read (A[i]);    Build_tree (1,1,n);    Vis[0]=++tot;        for (int i=2;i<=n;++i) {a[i]%=k;        Sum[i]=sum[i-1]+a[i];        if (sum[i]>=k) sum[i]-=k;    if (!vis[sum[i]]) Vis[sum[i]]=++tot;    } build (Rt[0],1,tot);        for (int i=1;i<=n;++i) {rt[i]=rt[i-1];    UPD (Rt[i],1,tot,vis[sum[i]);    } BFS ();    printf ("%lld\n", ans); return 0;}

Third question

We consider the case that the tree is a chain, we maintain the longest contiguous sub-segments with the line segment tree and we Can

So for a tree, we can use the tree chain to transform into a chain of cases

But notice that the Unicom block may be the concatenation of the chain and the chain, so we define a point right is the maximum prefix of all his sons and his different chains (minus 0) and his own point right

So the longest continuous sub-segment and the maximum value of all the chains is the answer.

We turn the changes into incremental changes

Modify the Logn bar chain at most each time you modify, we can maintain the affected points when we jump up.

About half an hour before the exam, and then the test found may be t

Then it took another half an hour to get the card constant, optimize the build process, and then practice a tree-shaped DP.

The results are still rank1qaq.

It is worth mentioning that maintaining the longest continuous field of all the chains and can be used in the heap, but I used another line in the Examination room tree Qaq

#include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> #include < Algorithm>using namespace Std; const int Maxn=100010;int n,m,u,v,type;int c[maxn];int h[maxn],cnt=0;struct edge{int to,next;} G[maxn<<1];int dep[maxn],sz[maxn],son[maxn],fa[maxn];int L[maxn],r[maxn],pos[maxn],fp[maxn],tot;int P[MAXN] , Top[maxn],sum;int mx[maxn<<2];int dp[maxn],tmp[maxn];struct seg_tree{int suf,pre,mx,sum;} t[maxn<<2];    void read (int &num) {int F=1;num=0;char ch=getchar (); while (ch< '! ')    Ch=getchar ();    if (ch== '-') F=-1,ch=getchar ();    while (ch>= ' 0 ' &&ch<= ' 9 ') num= (num<<1) + (num<<3) +ch-' 0 ', Ch=getchar (); Num*=f;} void Add (int x,int y) {++cnt; G[cnt].to=y; g[cnt].next=h[x];h[x]=cnt;}    void DFS (int u,int f) {sz[u]=1;fa[u]=f;        for (int i=h[u];i;i=g[i].next) {int v=g[i].to;        if (v==f) continue;        dep[v]=dep[u]+1;        DFS (V,u);        SZ[U]+=SZ[V];    if (Sz[son[u]]<sz[v]) son[u]=v;}return;}    void Get_pos (int u,int f) {top[u]=f;pos[u]=++tot;fp[tot]=u; if (u==f) {sum++;    L[sum]=tot;}    P[u]=sum;    if (!son[u]) {R[sum]=tot;return;}    Get_pos (SON[U],F);        for (int i=h[u];i;i=g[i].next) {int v=g[i].to; if (v==fa[u]| |        V==son[u]) continue;    Get_pos (V,V); }return;} int Max (int a,int b) {return a>b?a:b;}        void UPD (int o,int l,int r,int P,int v) {if (l==r) {t[o].suf+=v;t[o].pre+=v;        T[o].mx+=v;t[o].sum+=v;    Return    } int mid= (L+R) >>1;    if (p<=mid) UPD (O&LT;&LT;1,L,MID,P,V);    else UPD (O&LT;&LT;1|1,MID+1,R,P,V);    int l= (o<<1), r= (l|1);    T[o].sum=t[l].sum+t[r].sum;    T[o].suf=max (T[r].suf,t[r].sum+t[l].suf);    T[o].pre=max (T[l].pre,t[l].sum+t[r].pre);    T[o].mx=max (t[l].mx,t[r].mx); T[o].mx=max (T[o].mx,t[l].suf+t[r].pre);}        void build (int o,int l,int R) {if (l==r) {int u=fp[l];        T[o].suf=t[o].pre=t[o].mx=t[o].sum=dp[u];    Return    } int mid= (L+R) >>1; Build (O<<1,l,miD);    Build (O<<1|1,mid+1,r);    int l= (o<<1), r= (l|1);    T[o].sum=t[l].sum+t[r].sum;    T[o].suf=max (T[r].suf,t[r].sum+t[l].suf);    T[o].pre=max (T[l].pre,t[l].sum+t[r].pre);    T[o].mx=max (t[l].mx,t[r].mx); T[o].mx=max (T[o].mx,t[l].suf+t[r].pre);}    Seg_tree Ask (int o,int l,int r,int x,int y) {if (l>=x&&r<=y) return t[o];    int mid= (L+R) >>1;    if (Y<=mid) return ask (O<<1,l,mid,x,y);    else if (X>mid) return ask (O<<1|1,mid+1,r,x,y);        else{seg_tree A=ask (o<<1,l,mid,x,y);        Seg_tree B=ask (o<<1|1,mid+1,r,x,y), C;        C.sum=a.sum+b.sum;        C.suf=max (B.suf,b.sum+a.suf);        C.pre=max (A.pre,a.sum+b.pre);        C.mx=max (a.mx,b.mx);        C.mx=max (C.mx,a.suf+b.pre);    return C;    }}void Modify (int o,int l,int r,int P,int v) {if (l==r) {Mx[o]=v;return;}    int mid= (L+R) >>1;    if (p<=mid) modify (O&LT;&LT;1,L,MID,P,V);    else modify (O&LT;&LT;1|1,MID+1,R,P,V); Mx[o]=max (MX[O&LT;&LT;1],MX[O&LT;<1|1]);}        void get_upd (int u,int v) {while (u!=-1) {Seg_tree a=ask (1,1,n,l[p[u]],r[p[u]]);        UPD (1,1,N,POS[U],V);        Seg_tree B=ask (1,1,n,l[p[u]],r[p[u]);        Modify (1,1,sum,p[u],b.mx);        if (b.pre<0) b.pre=0;        if (a.pre<0) a.pre=0;    U=fa[top[u]];v=b.pre-a.pre; }return;}    void get_dp (int u,int f) {dp[u]=c[u];tmp[u]=c[u];    if (!son[u]) return;        for (int i=h[u];i;i=g[i].next) {int v=g[i].to; if (v==f| |        V==son[u]) continue;        GET_DP (V,u);    if (tmp[v]>0) dp[u]+=tmp[v];    }GET_DP (Son[u],u);    if (tmp[son[u]]>0) tmp[u]=dp[u]+tmp[son[u]]; else tmp[u]=dp[u];}    int main () {read (n); read (m);    for (int i=1;i<=n;++i) read (C[i]);        for (int i=1;i<n;++i) {read (u); Read (v);    Add (u,v); add (V,u); }dfs (1,-1);    Get_pos (a);    GET_DP (1,-1); build (1,1,n);    for (int i=1;i<=n;++i) printf ("%d%d\n", dp[i],tmp[i]);        for (int i=1;i<=sum;++i) {Seg_tree a=ask (1,1,n,l[i],r[i]); Modify (1,1,sum,i,a. mx);    }//for (int i=1;i<=n;++i) GET_UPD (I,c[i]);    for (int i=1;i<=n;++i) printf ("%d\n", ask (1,1,n,pos[i],pos[i]). sum);        while (m--) {read (type);        if (type==2) printf ("%d\n", Max (mx[1],0));            else{read (u); Read (v);            V=v-c[u];c[u]+=v;        GET_UPD (U,V); }} return 0;}

Today the exam learned some of the Chairman tree optimization techniques

Although the exam is stuck constant, and the second question data randomly by a big wave of water passed, very sad

But it's nice to learn new knowledge, Qaq.

Feel their own data structure ability is very good, generally have the idea of the need to maintain what data structure of the topic can be written quickly

Basically don't have to change to be able to shoot (except top_tree what)

The topic slightly some pits, the first question Eulerian graph caused own knowledge barrier, then can not understand the question to be able to explode zero

What's left of the question: some questions about the counting of graphs? I don't know if I can find it.

5.28 Exam Revision + Summary

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.