Because today is not modified, so we can only summarize the

And inexplicably rank1, seemingly because of my third problem of violence written roar?

First question

Looks like the Bzoj, ZCG they've done it.

But I didn't do it, I thought about it, it was a thin two-dollar relationship. Minimum cut

According to the Pty paper in the building method to get a bit, calculate K value after found that the figure must be a two-part map can be

And then think about it, random half an hour of data run discovery is a binary graph (this is the proof method of Oi

(I guess some particular nature of the subject determines that this is a dichotomy, yes, that's it)

So it was reassuring to write a two-figure coloring map Run min cut Qaq a dropped Qaq

As for the mathematical proof of the binary chart, it is this:

1, (a, B) = 1, so a, B is not all even

2, consider A, b are odd, may wish to set a=2*x-1,b=2*y-1

Then (2*x-1) ^2+ (2*y-1) ^2=2* (2*x^2-2*x+2*y^2-2*y+1)

It is not difficult to find that the exponent of the subsequent equation 2 is 1, so it is impossible to be a complete square number

Because no edges are built between the even numbers, there is no edge between the odd numbers, so the original is a two-part diagram

It is possible to directly divide the odd couple without the use of bipartite graph dyeing.

#include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include < iostream> #include <cmath> #include <queue>using namespace std;typedef long long ll;const int maxn=1010; const int Oo=0x7fffffff;int n,ans,s,t;int A[maxn],b[maxn];int h[maxn],cnt=1;int cur[maxn],col[maxn],vis[maxn];bool Check[maxn][maxn];struct edge{int to,next,w;} G[5000010];queue<int>q;int gcd (int a,int b) {return b==0?a:gcd (b,a%b);} void Add (int x,int y,int z=0) {++cnt; G[cnt].to=y; G[CNT].NEXT=H[X]; g[cnt].w=z;h[x]=cnt;} void read (int &num) {Num=0;char Ch=getchar (); while (ch< '! ') Ch=getchar (); while (ch>= ' 0 ' &&ch<= ' 9 ') num=num*10+ch-' 0 ', Ch=getchar ();} BOOL Judge (int a,int b) {int c=gcd (b); if (c!=1) return false; LL now=1ll*a*a+1ll*b*b;int k= (int) (sqrt (now)); if (1ll*k*k!=now) return False;return true; void Get_check () {for (int. i=1;i<=n;++i) {for (int j=i+1;j<=n;++j) {if (judge (A[i],a[j])) {check[i][j]=true;}}} return;} void Paint (int u) {for (int i=h[u];i;i=g[i].next{int v=g[i].to;if (COL[V]) continue;col[v]=3-col[u];p aint (v);} return;} void Get_paint () {for (int. i=1;i<=n;++i) {for (int j=i+1;j<=n;++j) {if (Check[i][j]) Add (i,j), add (J,i);}} for (int i=1;i<=n;++i) {if (!col[i]) col[i]=1,paint (i);}} void Build_graph () {memset (h,0,sizeof (h)); cnt=1; s=0; t=n+1;for (int i=1;i<=n;++i) {for (int j=i+1;j<=n;++j) {if (check[i][j]) {int u=i,v=j;if (col[u]!=1) swap (U,V); Add ( U,v,oo); add (v,u,0);}}} for (int i=1;i<=n;++i) {if (col[i]==1) Add (S,i,b[i]), add (i,s,0), else Add (I,t,b[i]), add (t,i,0);} return;} BOOL BFS () {Q.push (S); for (int i=s;i<=t;++i) Vis[i]=-1;vis[s]=0;while (! Q.empty ()) {int U=q.front (); Q.pop (); for (int i=h[u];i;i=g[i].next) {int v=g[i].to;if (vis[v]==-1&&g[i].w>0) {vis[v]=vis[u]+1; Q.push (v);}} return vis[t]!=-1;} int DFS (int x,int f) {if (x==t| | f==0) return f;int w,used=0;for (int i=cur[x];i;i=g[i].next) {if (vis[g[i].to]==vis[x]+1) {W=f-used;w=dfs (G[i].to,min ( W,G[I].W)); G[i].w-=w; G[i^1].w+=w;if (g[i].w>0) cur[x]=i;used+=w;if (used==f) return used;} if (!used) vis[x]=-1;return used;} void Dinic () {while (BFS ()) {for (int i=s;i<=t;++i) Cur[i]=h[i];ans-=dfs (S,oo);} return;} int main () {freopen ("number.in", "R", stdin), Freopen ("Number.out", "w", stdout); Read (n); for (int i=1;i<=n;++i) Read ( A[i]); for (int i=1;i<=n;++i) read (B[i]), ans+=b[i]; Get_check (); Get_paint (); Build_graph ();d inic ();p rintf ("%d\n", ans); return 0;}

Second question

The second question gives a bunch of inexplicable sets of orthogonal.

Since the time complexity of this topic is determined by the number of points to be read, it is not difficult to think of something imaginary tree

Consider how to use a tree to describe such a relationship

When the size of a set is 1, it's not hard to see that every given point is his father.

The elements of the collection are the elements that he represents to all the points of the root.

Consider the size of a set >1, it is not difficult to find the father of each point is a set of all points in the tree of LCA (i.e., the intersection of all points)

After we have built the tree we consider how to ask for some collection of the intersection, the examination time to think for a long time or to write a virtual tree

When I started writing, I found that this was a bare model for chaining, and then because one endpoint of each chain was the root, we sorted the points we read directly into the DFS order.

So the answer is the sum of the depth of all points minus the depth of the LCA of all adjacent two points and (in fact, this is almost the process of a virtual tree).

#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include < cstdlib>using namespace Std;const int maxn=200010;int n,k,x,n,m;int anc[maxn][20];int dep[maxn];int h[maxn],cnt=0; struct Edge{int to,next;} G[maxn<<1];int st[maxn],ed[maxn],tot=0;int s[maxn];bool cmp (const int &A,CONST int &b) {return st[a]< ST[B];} void Add (int x,int y) {++cnt; G[cnt].to=y; g[cnt].next=h[x];h[x]=cnt;} void read (int &num) {Num=0;char Ch=getchar (); while (ch< '! ') Ch=getchar (); while (ch>= ' 0 ' &&ch<= ' 9 ') num=num*10+ch-' 0 ', Ch=getchar ();} int LCA (int p,int q) {if (Dep[p]<dep[q]) swap (P,Q); int log;for (log=0; (1<<log) <=dep[p];++log);--log;for ( int i=log;i>=0;--i) {if (dep[p]-(1<<i) >=dep[q]) p=anc[p][i];} if (p==q) return p;for (int i=log;i>=0;--i) {if (Anc[p][i]!=-1&&anc[q][i]!=anc[p][i]) {P=anc[p][i];q=anc[q] [i];}} return anc[p][0];} void merge (int u,int f) {anc[u][0]=f;dep[u]=dep[f]+1;add (f,u); for (int i=1; (1<<i) <=n;++i) anc[u][i]=-1;for (int i=1; (1<<i) <=n;++i) {if (anc[u][i-1]!=-1) {int a=anc[u][i-1];anc[u][i]=anc[a][i-1];} else break;} return;} void Get_dfs (int u) {st[u]=++tot;for (int i=h[u];i;i=g[i].next) Get_dfs (g[i].to); ed[u]=tot;} int main () {freopen ("legend.in", "R", stdin), Freopen ("Legend.out", "w", stdout); Read (n); n=n+1;for (int i=0; (1<<i) <=n;++i) anc[0][i]=-1;for (int i=1;i<=n;++i) {read (k); if (!k) {merge (i,0); Continue;} Read (x); int now=x;for (int j=2;j<=k;++j) {read (x); Now=lca (now,x);} Merge (I,now);} Get_dfs (0); Read (m), while (m--) {read (k), for (int i=1;i<=k;++i) read (s[i]); sort (s+1,s+k+1,cmp); int ans=dep[s[1]]; for (int i=2;i<=k;++i) {ans+=dep[s[i]];int Now=lca (s[i],s[i-1]); Ans-=dep[now];} printf ("%d\n", ans);} return 0;}

Third question

The code seems to be 7k+.

I don't feel like writing.

Just give it a little bit of a blow.

First consider only the first limitation of the situation, which is very simple

We build the suffix tree, then do it again DFS, heuristic merge all suffixes

Whether the current node is legal if and only if the maximum value of the difference of the adjacent two suffixes cannot exceed the length of the current node

After we consider the second constraint, we consider where the current node first appears

It's not hard to find out what we're asking for is this first occurrence. is a suffix after stitching a suffix

This is what I want to do is to build a suffix automaton in the opposite way, and to maintain it during the heuristic merger.

The problem turned into a simple, recent public ancestor. Qaq so happy.

Yes, if you're going to build two Sam for a problem, write spaly heuristic merge, and then write a tree-chain split.

I don't think there's any need to write Qaq.

6.13 Exam Summary