POI2012
现在才开始写 POI 是不是太弱了?
怎么说呢,我发现我的代码好长啊~长啊~长啊~长长长长长长长长长长长长长长长长长长长长长长啊~
大概就是在一个内向树上搞一个类似 lca 的东西,想想内向树估计就可以搞出来了吧……
1 #include <cstdio> 2 const int sizeOfPoint=500005; 3 const int sizeOfEdge=500005; 4 5 inline int lg(int); 6 inline int min(int, int); 7 inline int max(int, int); 8 inline void swap(int & , int & ); 9 inline int getint(); 10 inline void putint(int); 11 12 struct edge {int point; edge * next;}; 13 edge memory[sizeOfEdge], * port=memory; 14 inline edge * newedge(int, edge * ); 15 16 struct node {int x, y; inline node(int=0, int=0);}; 17 inline bool operator < (node, node); 18 19 int n, m, k; 20 int p[sizeOfPoint]; 21 edge * e[sizeOfPoint]; 22 int a[32][sizeOfPoint]; 23 int g[sizeOfPoint], s[sizeOfPoint]; 24 int f[sizeOfPoint], d[sizeOfPoint]; 25 int l[sizeOfPoint]; 26 bool v[sizeOfPoint], b[sizeOfPoint]; 27 inline void bfs(int); 28 inline int lca(int, int); 29 30 int main() 31 { 32 n=getint(), k=getint(); 33 for (int i=1;i<=n;i++) 34 { 35 p[i]=getint(); 36 e[p[i]]=newedge(i, e[p[i]]); 37 } 38 39 for (int i=1;i<=n;i++) if (!v[i]) 40 { 41 int u=i; 42 for ( ;!b[u];u=p[u]) b[u]=true; 43 44 ++m; 45 for (int j=1;!l[u];j++, u=p[u]) 46 { 47 g[u]=m; 48 s[m]++; 49 l[u]=j; 50 bfs(u); 51 } 52 } 53 54 for (int i=1;i<=k;i++) 55 { 56 int a=getint(), b=getint(); 57 58 if (g[f[a]]!=g[f[b]]) 59 { 60 putint(-1), putchar(' '); 61 putint(-1), putchar('\n'); 62 } 63 else if (f[a]==f[b]) 64 { 65 int c=lca(a, b); 66 putint(d[a]-d[c]), putchar(' '); 67 putint(d[b]-d[c]), putchar('\n'); 68 } 69 else 70 { 71 int o=s[g[f[a]]]; 72 node ans1=node(d[a], d[b]), ans2=node(d[a], d[b]); 73 74 if (l[f[a]]<l[f[b]]) 75 { 76 ans1.x+=l[f[b]]-l[f[a]]; 77 ans2.y+=o-(l[f[b]]-l[f[a]]); 78 } 79 else 80 { 81 ans1.x+=o-(l[f[a]]-l[f[b]]); 82 ans2.y+=l[f[a]]-l[f[b]]; 83 } 84 85 if (ans1<ans2) 86 { 87 putint(ans1.x), putchar(' '); 88 putint(ans1.y), putchar('\n'); 89 } 90 else 91 { 92 putint(ans2.x), putchar(' '); 93 putint(ans2.y), putchar('\n'); 94 } 95 } 96 } 97 98 return 0; 99 } 100 101 inline int lg(int x) 102 { 103 return 31-__builtin_clz(x); 104 } 105 inline int min(int x, int y) 106 { 107 return x<y?x:y; 108 } 109 inline int max(int x, int y) 110 { 111 return x>y?x:y; 112 } 113 inline void swap(int & x, int & y) 114 { 115 int t=x; x=y; y=t; 116 } 117 inline int getint() 118 { 119 register int num=0; 120 register char ch; 121 do ch=getchar(); while (ch<'0' || ch>'9'); 122 do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9'); 123 return num; 124 } 125 inline void putint(int num) 126 { 127 char stack[11]; 128 register int top=0; 129 if (num==0) stack[top=1]='0'; 130 if (num<0) putchar('-'), num=-num; 131 for ( ;num;num/=10) stack[++top]=num%10+'0'; 132 for ( ;top;top--) putchar(stack[top]); 133 } 134 135 inline edge * newedge(int point, edge * next) 136 { 137 edge * ret=port++; 138 ret->point=point; ret->next=next; 139 return ret; 140 } 141 142 inline node::node(int _x, int _y) 143 { 144 x=_x; 145 y=_y; 146 } 147 inline bool operator < (node a, node b) 148 { 149 if (max(a.x, a.y)<max(b.x, b.y)) return true; 150 if (max(a.x, a.y)>max(b.x, b.y)) return false; 151 if (min(a.x, a.y)<min(b.x, b.y)) return true; 152 if (min(a.x, a.y)>min(b.x, b.y)) return false; 153 return a.y<b.y; 154 } 155 156 inline void bfs(int root) 157 { 158 static int q[sizeOfPoint]; 159 int s=0, t=0; 160 d[root]=0; 161 f[root]=root; 162 163 for (q[t++]=root;s<t;s++) 164 { 165 int u=q[s]; 166 v[u]=true; 167 if (d[u]>1) 168 { 169 int lim=lg(d[u]); 170 for (int i=1;i<=lim;i++) 171 a[i][u]=a[i-1][a[i-1][u]]; 172 } 173 174 for (edge * i=e[u];i;i=i->next) if (i->point!=p[u] && !l[i->point]) 175 { 176 d[i->point]=d[u]+1; 177 f[i->point]=root; 178 a[0][i->point]=u; 179 q[t++]=i->point; 180 } 181 } 182 } 183 inline int lca(int u, int v) 184 { 185 int dist; 186 if (d[u]<d[v]) swap(u, v); 187 while ((dist=d[u]-d[v])) u=a[__builtin_ctz(dist)][u]; 188 if (u==v) return u; 189 for (int i=31;i>=0;i--) 190 if (a[i][u]!=a[i][v]) 191 u=a[i][u], 192 v=a[i][v]; 193 return a[0][u]; 194 }
-Distance
一道我认为做法极其诡异的题目,很容易想到若令 g[i] 表示 i 有几个质因子,则 d[x, y]=g[x]+g[y]-2*g[gcd(x, y)]
然后我就想不下去了……一看题解,居然是枚举 x 的因数!然后暴力搞搞就出来了,细节部分要仔细推敲。
还有 n 的质因子数应该是 O(log2n) 所以 n 的因子数最差情况似乎是 O(n) 级别的?也只能说是数据弱了~
1 #include <cstdio> 2 #include <cstring> 3 const int sizeOfNumber=100001; 4 const int sizeOfSieve=1000001; 5 const int inf=0x7F7F7F7F; 6 7 inline int getint(); 8 inline void putint(int); 9 10 bool b[sizeOfSieve]; 11 int m, p[sizeOfNumber]; 12 int e[sizeOfSieve], c[sizeOfSieve]; 13 inline void sieve(); 14 15 struct node {int v, t; inline node(int=0, int=0);}; 16 17 int n, l; 18 int ansv, anst; 19 int a[sizeOfNumber]; 20 node s[sizeOfNumber]; 21 int v1[sizeOfSieve], v2[sizeOfSieve]; 22 int t1[sizeOfSieve], t2[sizeOfSieve]; 23 void search(int, int); 24 void query(int, int); 25 26 int main() 27 { 28 sieve(); 29 30 n=getint(); 31 for (int i=1;i<=n;i++) 32 a[i]=getint(); 33 34 memset(v1, 0x7F, sizeof(v1)); 35 memset(v2, 0x7F, sizeof(v2)); 36 for (int i=1;i<=n;i++) 37 { 38 int t=a[i]; 39 40 s[0]=node(0, 0); 41 for (l=0;t>1;t/=e[t]) 42 { 43 if (e[t]!=s[l].v) 44 s[++l]=node(e[t], 1); 45 else 46 s[l].t++; 47 } 48 s[0]=node(a[i], i); 49 search(1, 1); 50 } 51 for (int i=1;i<=n;i++) 52 { 53 int t=a[i]; 54 55 s[0]=node(0, 0); 56 for (l=0;t>1;t/=e[t]) 57 { 58 if (e[t]!=s[l].v || !l) 59 s[++l]=node(e[t], 1); 60 else 61 s[l].t++; 62 } 63 s[0]=node(a[i], i); 64 65 ansv=anst=inf; 66 query(1, 1); 67 putint(anst); 68 } 69 70 return 0; 71 } 72 73 inline int getint() 74 { 75 register int num=0; 76 register char ch; 77 do ch=getchar(); while (ch<'0' || ch>'9'); 78 do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9'); 79 return num; 80 } 81 inline void putint(int num) 82 { 83 char stack[11]; 84 register int top=0; 85 if (num==0) stack[top=1]='0'; 86 for ( ;num;num/=10) stack[++top]=num%10+'0'; 87 for ( ;top;top--) putchar(stack[top]); 88 putchar('\n'); 89 } 90 91 inline void sieve() 92 { 93 for (int i=2;i<sizeOfSieve;i++) 94 { 95 if (!b[i]) 96 { 97 p[m++]=i; 98 e[i]=i; c[i]=1; 99 } 100 101 for (int j=0;j<m;j++) 102 { 103 if (i*p[j]>=sizeOfSieve) break; 104 b[i*p[j]]=true; 105 e[i*p[j]]=p[j]; c[i*p[j]]=c[i]+1; 106 if (e[i]==p[j]) break; 107 } 108 } 109 } 110 111 inline node::node(int _v, int _t) 112 { 113 v=_v, t=_t; 114 } 115 116 void search(int v, int t) 117 { 118 if (t>l) 119 { 120 int g=c[s[0].v]-(c[v]<<1); 121 if (g<v1[v]) 122 { 123 v2[v]=v1[v], t2[v]=t1[v]; 124 v1[v]=g, t1[v]=s[0].t; 125 } 126 else if (g<v2[v]) 127 v2[v]=g, t2[v]=s[0].t; 128 } 129 else 130 { 131 for (int i=0, j=1;i<=s[t].t;i++, j=j*s[t].v) 132 search(v*j, t+1); 133 } 134 } 135 void query(int v, int t) 136 { 137 if (t>l) 138 { 139 if (s[0].t!=t1[v]) 140 { 141 if (v1[v]<ansv || (v1[v]==ansv && t1[v]<anst)) 142 ansv=v1[v], anst=t1[v]; 143 } 144 else if (v2[v]<ansv || (v2[v]==ansv && t2[v]<anst)) 145 ansv=v2[v], anst=t2[v]; 146 } 147 else 148 { 149 for (int i=0, j=1;i<=s[t].t;i++, j=j*s[t].v) 150 query(v*j, t+1); 151 } 152 }
-Letters
这道题目应该还是比较简单的吧,一眼就看出是求逆序对数,利用第一个字符串给第二个字符串标号(是字母对应字母的标号,开 26 个队列即可)
本质其实和直接算逆序对数是一样的,只不过这道题可以看作是对 “顺序” 重新下了一个定义罢了~
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 typedef long long LL; 5 const int sizeOfString=1000001; 6 7 inline int getint(); 8 inline int getstr(char * ); 9 inline void putint(LL); 10 11 int C[sizeOfString]; 12 inline int lowbit(int); 13 inline void update(int); 14 inline int query(int); 15 16 int N; 17 char J[sizeOfString], M[sizeOfString]; 18 std::queue<int> q[26]; 19 int A[sizeOfString]; 20 21 int main() 22 { 23 LL ans=0; 24 25 N=getint(); 26 getstr(J); 27 getstr(M); 28 29 for (int i=0;i<N;i++) 30 q[J[i]-'A'].push(i); 31 for (int i=0;i<N;i++) 32 { 33 A[i]=1+q[M[i]-'A'].front(); 34 q[M[i]-'A'].pop(); 35 } 36 37 for (int i=0;i<N;i++) 38 { 39 ans+=query(A[i]); 40 update(A[i]); 41 } 42 43 putint(ans); 44 45 return 0; 46 } 47 48 inline int getint() 49 { 50 register int num=0; 51 register char ch; 52 do ch=getchar(); while (ch<'0' || ch>'9'); 53 do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9'); 54 return num; 55 } 56 inline int getstr(char * str) 57 { 58 register int len=0; 59 register char ch; 60 do ch=getchar(); while (ch<'A' || ch>'Z'); 61 do str[len++]=ch, ch=getchar(); while (ch>='A' && ch<='Z'); 62 return len; 63 } 64 inline void putint(LL num) 65 { 66 char stack[22]; 67 register int top=0; 68 if (num==0) stack[top=1]='0'; 69 for ( ;num;num/=10) stack[++top]=num%10+'0'; 70 for ( ;top;top--) putchar(stack[top]); 71 putchar('\n'); 72 } 73 74 inline int lowbit(int i) 75 { 76 return i & -i; 77 } 78 inline void update(int i) 79 { 80 for ( ;i;i-=lowbit(i)) 81 C[i]++; 82 } 83 inline int query(int i) 84 { 85 int ret=0; 86 for ( ;i<=N;i+=lowbit(i)) 87 ret+=C[i]; 88 return ret; 89 }