官方解题报告http://blog.sina.com.cn/s/blog_a19ad7a10102uyes.html
B. Jump
最小K路径覆盖的模型,用费用流或者KM算法解决,构造二部图,X部有N*M个节点,源点向X部每个节点连一条边,流量1,费用0,Y部有N*M个节点,每个节点向汇点连一条边,流量1,费用0,如果X部的节点x可以在一步之内到达Y部的节点y,那么就连边x->y,费用为从x格子到y格子的花费能量减去得到的能量,流量1,再在X部增加一个新的节点,表示可以从任意节点出发K次,源点向其连边,费用0,流量K,这个点向Y部每个点连边,费用0,流量1,最这个图跑最小费用最大流,如果满流就是存在解,反之不存在,最小费用的相反数就是可以获得的最大能量
C. Centroid of a Tree
首先找出重心,之后以重心为根进行树形dp,用dp[i][j]表示以编号为i的节点为根的子树有j个儿子的方案数 ,这个直接合并,每次合并两个子树的时候枚举两个子树的儿子的个数,对于树上每条边合并一次,总共合并n 次,每次合并的复杂度是n^2,这个是三方的复杂度。
对于有两个重心的情况,首先将这两个子树中间的边打断变成两个树,对这两个树分别按照上述方法处理出dp 数组,如果要使得重心位置不变,那么这两个子树需要有相同的节点个数,这个直接枚举一下然后两边乘起来 就好了。
至于只有一个重心的情况,还是按照上述方法处理出dp数组,为了计算合法的方案数,我们用总的方案数减去 不合法的方案数,对于不合法的情况,去掉这个根后一定会有一个最大的分支,这个分支的节点数超过剩下的 全部分支加起来的节点个数,所以先枚举最大分支,对于剩下的分支用背包处理,f[i]表示剩下的全部子树取i 个节点的方案数,这个很容易处理,处理完之后枚举一下最大分支的节点个数,再利用f数组就可以算出在这种 情况下的非法的方案数了。
对于这里的复杂度要特别说明一下,设每个分支的节点数是x1,x2,x3...,xk,合并的复杂度是x1*x2+(x1+x2) *x3+...+(x1+x2+...+xk-1)*xk<=(x1+x2+...+xk)^2=n^2,加上枚举是三方,所以整个dp的总复杂度是三方的。
D. Task
基本思想是贪心。
对于价值c=500*xi+2*yi,yi最大影响100*2<500,所以就是求xi总和最大。可以先对机器和任务的时间从大到小排序。从最大时间的任务开始,找出满足任务时间要求的所有机器,从中找出等级最低且满足任务等级要求的机器匹配。依次对任务寻找满足要求的机器。
F. Shooting
将所有目标与起点线的距离离散化作为下标,建立函数式线段树,将距离按区间端点从1到X的顺序加入函数式线段树,左端点+1,右端点-1,记录区间元素的距离和,以及元素的个数。对于在x位置的询问,找到其对应的端点,这个可以二分找到,然后在该端点对应的线段树上进行二分查找求解,最后判断前一个答案与P的大小得到当前问题的答案。
G. Xor
线段树,时间复杂度是O(5000*200*logn+10*m*logn)。
f[ prefix ]保存2进制前缀状态,合并就暴力,比如
101xxx
11xxxx
x表示0或者1
前缀固定 后面随便取
这2个xor的结果
只有前2位是确定的
合并完大约就是
01xxxx
然后方案数就可以算了,可以证明,状态不会太多。
H. Information Extraction
本题要求大家能够存储特定的输出格式以及若干种HTML结构和映射关系,根据输入的HTML文本,寻找其结构,如果找不到结构与之匹配,输出“Can't Identify”,如果只有一个,根据映射关系以及输出格式的要求输出结果,如果有多个,则使用最早输入的那个结构。
解决以下几点即可
1、对HTML输入的读取
2、判断结构是不是输入的HTML文本的结构
3、根据映射以及输出格式的要求输出结果
注意映射关系中可能有一个id到多个标签,并且这些标签在输入格式中是存在多个的。
I. Turn the pokers
最终的结果一定是连续出现的,只需要求出最终的区间。
因为如果对同一张牌进行两次操作,牌的状态不改变。故牌的翻转次数一定是减少偶数次。如果所有数的和是奇数,那么最终结果也一定是奇数。同理,偶数也是一样的。
所以只要递推求出最后的区间,计算sum(C(xi,m)(i=0,1,2。。。)),m是总牌数,xi是在区间内连续的奇数或偶数,在模10^9+9就是最终的答案。
J. Rating
令(x, y)表示高分为x,低分为y的状态(x >= y),E(x, y)表示从(x, y)到达(1000, ?)的比赛场数期望。容易得到E(x, y) = P * E(x1, y1) + (1 - P) * E(x2, y2) + 1,其中,(x1, y1)表示rating上升后的状态,(x2, y2)表示rating下降后的状态。把E(1000, ?) = 0带入可以得到包含n个未知数的n个方程,n大概200多,可以高斯消元。E(0, 0)即为答案。
K. Shortest-path tree
首先构造最短路径树。先求根节点到其他节点的最短路径,然后从根节点开始进行深度优先遍历,先遍历节点编号较小的没遍历过的儿子,这样就能处理处最短路径树。
之后找节点数为K的树链。可以用树分治进行求解,在树分治求解过程中,对于每个中心点,处理出该子树中所有节点到中心点的树链,然后枚举每条树链,比如某条树链节点为a,长度为b,则找之前遍历过的树链中节点数位K-a的长度最长的树链,将这两条树链拼起来可以得到节点数为K的树链,用其更新答案。最好一个一个分支分别处理,可以避免考虑同一个分支来的两条树链。这样枚举并且更新信息,还要存方案数。
Couple doubi http://acm.hdu.edu.cn/showproblem.php?pid=4861
找规律。
1 #include<cstdio> 2 using namespace std; 3 int main(){ 4 int n,p; 5 while(~scanf("%d%d",&n,&p)){ 6 if(n/(p-1)&1)puts("YES"); 7 else puts("NO"); 8 } 9 return 0; 10 }
Jump http://acm.hdu.edu.cn/showproblem.php?pid=4862
最小费用最大流。id[][]给每个点标号表示左侧,id[][]+cnt表示右侧点,源点s连每一个左侧点,每一个右侧点连到汇点en。流量都是1,费用都是0。在一个中间点ps,源点s到他k的流,ps到每一个右侧点1的流,因为走k次,这里也就相当于这个点不经过其他点,直接流向en,但只有k个起点。题目要求赚最大能量,把能量取个相反数,当做费用,这样求的最小费用的绝对值就是最大能量了。
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #define mt(a,b) memset(a,b,sizeof(a)) 5 using namespace std; 6 const int M=1010; 7 const int inf = 0x3f3f3f3f; 8 class MaxflowMincost { //最小费用最大流 9 struct E { 10 int u,v,next,flow,cost; 11 } e[M<<4]; 12 queue<int> q; 13 int le,flow,cost,head[M],cur[M],dis[M],pre[M]; 14 bool used[M],sign[M]; 15 public: 16 int getcost() { 17 return cost; 18 } 19 int getflow() { 20 return flow; 21 } 22 bool spfa(int s,int t) { 23 mt(used,0); 24 mt(sign,0); 25 mt(dis,0); 26 while(!q.empty()) q.pop(); 27 q.push(s); 28 used[s]=sign[s]=true; 29 while(!q.empty()) { 30 int u=q.front(); 31 q.pop(); 32 used[u]=false; 33 for(int i=head[u]; ~i; i=e[i].next) { 34 if(e[i].flow<1) continue; 35 int v=e[i].v; 36 if(!sign[v]||dis[v]>dis[u]+e[i].cost) { 37 dis[v]=dis[u]+e[i].cost; 38 sign[v]=true; 39 pre[v]=u; 40 cur[v]=i; 41 if(used[v]) continue; 42 used[v]=true; 43 q.push(v); 44 } 45 } 46 } 47 return sign[t]; 48 } 49 void init() { 50 le=0; 51 mt(head,-1); 52 } 53 void add(int u,int v,int flow,int cost) { 54 e[le].u=u; 55 e[le].v=v; 56 e[le].flow=flow; 57 e[le].cost=cost; 58 e[le].next=head[u]; 59 head[u]=le++; 60 e[le].u=v; 61 e[le].v=u; 62 e[le].flow=0; 63 e[le].cost=-cost; 64 e[le].next=head[v]; 65 head[v]=le++; 66 } 67 void solve(int s,int t) { 68 flow=cost=0; 69 while(spfa(s,t)) { 70 int temp=t; 71 int now=inf; 72 while(temp!=s) { 73 now=min(now,e[cur[temp]].flow); 74 temp=pre[temp]; 75 } 76 flow+=now; 77 temp=t; 78 while(temp!=s) { 79 cost+=now*e[cur[temp]].cost; 80 e[cur[temp]].flow-=now; 81 e[cur[temp]^1].flow+=now; 82 temp=pre[temp]; 83 } 84 } 85 } 86 } gx; 87 char str[16][16]; 88 int id[16][16]; 89 int main() { 90 int T,n,m,k; 91 while(~scanf("%d",&T)) { 92 int cas=1; 93 while(T--) { 94 scanf("%d%d%d",&n,&m,&k); 95 for(int i = 0; i < n; i++) 96 scanf("%s",str[i]); 97 printf("Case %d : ",cas++); 98 gx.init(); 99 int cnt=0; 100 for(int i=0;i<n;i++){ 101 for(int j=0;j<m;j++){ 102 id[i][j]=cnt++; 103 } 104 } 105 int st=cnt++; 106 int ps=cnt++; 107 int en=cnt++; 108 gx.add(st,ps,k,0); 109 for(int i = 0; i < n; i++){ 110 for(int j = 0,w; j < m; j++) { 111 gx.add(st,id[i][j],1,0); 112 gx.add(id[i][j]+cnt,en,1,0); 113 gx.add(ps,id[i][j]+cnt,1,0); 114 for(int y = j+1; y < m; y++) { 115 w=y-j-1; 116 if(str[i][y] == str[i][j]) 117 w-=str[i][j]-'0'; 118 gx.add(id[i][j],id[i][y]+cnt,1,w); 119 } 120 for(int x = i+1; x < n; x++) { 121 w=x-i-1; 122 if(str[x][j] == str[i][j]) 123 w-=str[i][j]-'0'; 124 gx.add(id[i][j],id[x][j]+cnt,1,w); 125 } 126 } 127 } 128 gx.solve(st,en); 129 int flow=gx.getflow(); 130 int cost=gx.getcost(); 131 if(flow != n*m)printf("-1 "); 132 else printf("%d ",-cost); 133 } 134 } 135 return 0; 136 }
Centroid of a Tree http://acm.hdu.edu.cn/showproblem.php?pid=4863
dfs是树形dp找重心,然后看看有几个重心,不是一个就是两个,分两种情况讨论,如果是两个重心,将重心之间的边断开,两边分别DFS处理出dp[i][j]表示i号节点为根的子树有j个儿子的方案数。这里还没全懂。
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<algorithm> 5 #define mt(a,b) memset(a,b,sizeof(a)) 6 using namespace std; 7 const int M=512; 8 const int mod=10007; 9 struct G { 10 struct E { 11 int u,v,next; 12 bool flag; 13 } e[M*M]; 14 int le,head[M]; 15 void init() { 16 le=0; 17 mt(head,-1); 18 } 19 void add(int u,int v) { 20 e[le].u=u; 21 e[le].v=v; 22 e[le].flag=true; 23 e[le].next=head[u]; 24 head[u]=le++; 25 } 26 } g; 27 int n,num[M],big[M]; 28 void dfs(int u,int fa) { //find center 29 num[u]=1; 30 big[u]=0; 31 for(int i=g.head[u]; ~i; i=g.e[i].next) { 32 int v=g.e[i].v; 33 if(v!=fa) { 34 dfs(v,u); 35 num[u]+=num[v]; 36 big[u]=max(big[u],num[v]); 37 } 38 } 39 big[u]=max(big[u],n-num[u]); 40 } 41 struct S{ 42 int id,val; 43 friend bool operator <(S a,S b){ 44 return a.val<b.val; 45 } 46 }b[M]; 47 int dp[M][M];//dp[i][j]表示以编号为i的节点为根的子树有j个儿子的方案数 48 int save[M]; 49 void DFS(int u,int fa) { 50 for(int i=0; i<=n; i++) dp[u][i]=0; 51 dp[u][0]=1; 52 int T=0; 53 for(int i=g.head[u]; ~i; i=g.e[i].next) { 54 if(g.e[i].flag) { 55 int v=g.e[i].v; 56 if(v!=fa) { 57 DFS(v,u); 58 for(int j=0; j<=n; j++) save[j]=0; 59 for(int a=0; a<=T; a++) 60 for(int b=0; b<=num[v]; b++) { 61 int add=(dp[u][a]*dp[v][b])%mod; 62 save[a+b]=(save[a+b]+add)%mod; 63 } 64 for(int a=0; a<=n; a++) 65 dp[u][a]=save[a]; 66 T+=num[v]; 67 } 68 } 69 } 70 for(int i=n; i>=0; i--) 71 dp[u][i+1]=dp[u][i]; 72 dp[u][0]=1; 73 } 74 int f[2][M]; 75 int main() { 76 int t,x,y; 77 while(~scanf("%d",&t)) { 78 int cas=1; 79 while(t--) { 80 scanf("%d",&n); 81 g.init(); 82 for(int i=0;i<n-1;i++) { 83 scanf("%d%d",&x,&y); 84 g.add(x,y); 85 g.add(y,x); 86 } 87 printf("Case %d: ",cas++); 88 dfs(1,-1); 89 int lb=0; 90 for(int i=1;i<=n;i++){ 91 b[lb].id=i; 92 b[lb].val=big[i]; 93 lb++; 94 } 95 sort(b,b+lb); 96 if((lb>1&&b[0].val<b[1].val)||lb==1){ //一个重心 97 int rt=b[0].id; 98 dfs(rt,-1); 99 DFS(rt,-1); 100 int ans=1; 101 for(int i=g.head[rt]; ~i; i=g.e[i].next) { 102 int v=g.e[i].v; 103 int T=0; 104 for(int j=0; j<=n; j++) 105 T=(T+dp[v][j])%mod; 106 ans=(ans*T)%mod; 107 } 108 for(int i=g.head[rt]; ~i; i=g.e[i].next) { 109 int x=g.e[i].v; 110 int T=0; 111 int now=0; 112 int pre=1; 113 memset(f,0,sizeof(f)); 114 f[now][0]=1; 115 for(int j=g.head[rt];~j;j=g.e[j].next){ 116 if(i == j) continue; 117 int y=g.e[j].v; 118 now^=1; 119 pre^=1; 120 for(int a=0; a<=n; a++) 121 f[now][a]=0; 122 for(int a=0; a<=T; a++) 123 for(int b=0; b<=num[y]; b++) { 124 f[now][a+b]+=f[pre][a]*dp[y][b]; 125 f[now][a+b]%=mod; 126 } 127 T+=num[y]; 128 } 129 int sum=0; 130 for(int j=1; j<=n; j++) { 131 sum=(sum+f[now][j-1])%mod; 132 int add=(dp[x][j]*sum)%mod; 133 ans=(ans-add+mod)%mod; 134 } 135 } 136 printf("%d ",ans); 137 } else { //two center 138 int x=b[0].id; 139 int y=b[1].id; 140 for(int i=0;i<g.le;i++){ 141 if((g.e[i].u==x&&g.e[i].v==y)||(g.e[i].u==y&&g.e[i].v==x)){ 142 g.e[i].flag=false; 143 g.e[i^1].flag=false; 144 break; 145 } 146 } 147 DFS(x,-1); 148 DFS(y,-1); 149 int ans=0; 150 for(int i=1; i<=n; i++) { 151 int add=(dp[x][i]*dp[y][i])%mod; 152 ans=(ans+add)%mod; 153 } 154 printf("%d ",ans); 155 } 156 } 157 } 158 return 0; 159 }
Task http://acm.hdu.edu.cn/showproblem.php?pid=4864
二级排序,然后对x单调队列,y标记然后暴力找最接近的一个。y是100,所以复杂度o(m*100)。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<cmath> 5 #include<cctype> 6 #include<iostream> 7 #include<algorithm> 8 #include<queue> 9 #define mt(a,b) memset(a,b,sizeof(a)) 10 using namespace std; 11 typedef __int64 LL; 12 const int M=100010; 13 struct NODE{ 14 int x,y; 15 friend bool operator <(NODE a,NODE b){ 16 if(a.x==b.x) return a.y>b.y; 17 return a.x>b.x; 18 } 19 }mach[M],task[M]; 20 int ma[128]; 21 int main(){ 22 int n,m; 23 while(~scanf("%d%d",&n,&m)){ 24 mt(ma,0); 25 for(int i=0;i<n;i++){ 26 scanf("%d%d",&mach[i].x,&mach[i].y); 27 } 28 for(int i=0;i<m;i++){ 29 scanf("%d%d",&task[i].x,&task[i].y); 30 } 31 sort(mach,mach+n); 32 sort(task,task+m); 33 int ans=0; 34 LL sum=0; 35 int id=0; 36 for(int i=0;i<m;i++){ 37 while(mach[id].x>=task[i].x&&id<n){ 38 ma[mach[id].y]++; 39 id++; 40 } 41 for(int j=task[i].y;j<=100;j++){ 42 if(ma[j]){ 43 ma[j]--; 44 ans++; 45 sum+=500*task[i].x+2*task[i].y; 46 break; 47 } 48 } 49 } 50 printf("%d %I64d ",ans,sum); 51 } 52 return 0; 53 }
Peter's Hobby http://acm.hdu.edu.cn/showproblem.php?pid=4865
dp求一个概率最大的序列,记录路径,类似上海邀请赛c。
1 #include<cstdio> 2 #include<cstring> 3 #define mt(a,b) memset(a,b,sizeof(a)) 4 const int M=64; 5 char yezi[4][8]={"Dry","Dryish","Damp","Soggy"}; 6 char tian[3][8]={"Sunny","Cloudy","Rainy"}; 7 int a[M]; 8 char op[8]; 9 double dp[M][3]; 10 int pre[M][3]; 11 int ans[M]; 12 double f[3][4]={ 13 0.60,0.20,0.15,0.05, 14 0.25,0.30,0.20,0.25, 15 0.05,0.10,0.35,0.50, 16 }; 17 double s[3][3]={ 18 0.500,0.375,0.125, 19 0.250,0.125,0.625, 20 0.250,0.375,0.375, 21 }; 22 int main(){ 23 int t,n; 24 while(~scanf("%d",&t)){ 25 int cas=1; 26 while(t--){ 27 scanf("%d",&n); 28 for(int i=1;i<=n;i++){ 29 scanf("%s",op); 30 for(int j=0;j<4;j++){ 31 if(!strcmp(op,yezi[j])){ 32 a[i]=j; 33 break; 34 } 35 } 36 } 37 mt(dp,0); 38 mt(pre,-1); 39 dp[1][0]=0.63*f[0][a[1]]; 40 dp[1][1]=0.17*f[1][a[1]]; 41 dp[1][2]=0.20*f[2][a[1]]; 42 for(int i=2;i<=n;i++){ 43 for(int j=0;j<3;j++){ 44 for(int k=0;k<3;k++){ 45 if(dp[i][j]<dp[i-1][k]*s[k][j]*f[j][a[i]]){ 46 dp[i][j]=dp[i-1][k]*s[k][j]*f[j][a[i]]; 47 pre[i][j]=k; 48 } 49 } 50 } 51 } 52 double big=0; 53 int id; 54 for(int i=0;i<3;i++){ 55 if(big<dp[n][i]){ 56 big=dp[n][i]; 57 id=i; 58 } 59 } 60 int la=0; 61 int x=n; 62 ans[la++]=id; 63 while(pre[x][id]!=-1){ 64 id=pre[x][id]; 65 ans[la++]=id; 66 x--; 67 } 68 printf("Case #%d: ",cas++); 69 for(int i=la-1;i>=0;i--){ 70 puts(tian[ans[i]]); 71 } 72 } 73 } 74 return 0; 75 }
Shooting http://acm.hdu.edu.cn/showproblem.php?pid=4866
主席树,待补。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int MAXN = 200010; 5 const int M = MAXN * 100; 6 int n,tot; 7 int T[MAXN]; 8 int lson[M],rson[M]; 9 int c1[M]; 10 long long c2[M]; 11 int build(int l,int r) { 12 int root = tot++; 13 c1[root] = 0; 14 c2[root] = 0; 15 if(l != r) { 16 int mid = (l+r)/2; 17 lson[root] = build(l,mid); 18 rson[root] = build(mid+1,r); 19 } 20 return root; 21 } 22 int update(int root,int pos,int val1,long long val2) { 23 int newroot = tot++, tmp = newroot; 24 c1[newroot] = c1[root] + val1; 25 c2[newroot] = c2[root] + val2; 26 int l = 1, r = n; 27 while(l < r) { 28 int mid = (l+r)/2; 29 if(pos <= mid) { 30 lson[newroot] = tot++; 31 rson[newroot] = rson[root]; 32 newroot = lson[newroot]; 33 root = lson[root]; 34 r = mid; 35 } else { 36 rson[newroot] = tot++; 37 lson[newroot] = lson[root]; 38 newroot = rson[newroot]; 39 root = rson[root]; 40 l = mid+1; 41 } 42 c1[newroot] = c1[root] + val1; 43 c2[newroot] = c2[root] + val2; 44 } 45 return tmp; 46 } 47 long long query(int root,int K) { 48 long long ret = 0; 49 int l = 1, r = n; 50 while(l < r) { 51 int mid = (l+r)/2; 52 if(c1[lson[root]] >= K) { 53 r = mid; 54 root = lson[root]; 55 } else { 56 K -= c1[lson[root]]; 57 ret += c2[lson[root]]; 58 root = rson[root]; 59 l = mid+1; 60 } 61 } 62 return ret + c2[root]; 63 } 64 struct Node { 65 int x; 66 int D; 67 int index; 68 Node(int _x = 0,int _D = 0,int _index = 0) { 69 x = _x; 70 D = _D; 71 index = _index; 72 } 73 } node[MAXN]; 74 bool cmp(Node a,Node b) { 75 if(a.x != b.x)return a.x < b.x; 76 else return a.D > b.D; 77 } 78 int y[MAXN]; 79 int ind[MAXN]; 80 bool cmp2(int a,int b) { 81 return y[a] < y[b]; 82 } 83 int rind[MAXN]; 84 int main() { 85 int N,MM,X,P; 86 while(~scanf("%d%d%d%d",&N,&MM,&X,&P)) { 87 tot = 0; 88 int cnt = 0; 89 int cnty = 0; 90 int L,R,D; 91 for(int i = 0; i < N; i++) { 92 scanf("%d%d%d",&L,&R,&D); 93 y[cnty++] = D; 94 ind[i] = i; 95 node[++cnt] = Node(L,D,i); 96 node[++cnt] = Node(R,-D,i); 97 } 98 sort(ind,ind+N,cmp2); 99 for(int i = 0; i < N; i++) 100 rind[ind[i]] = i+1; 101 n = N; 102 sort(node+1,node+cnt+1,cmp); 103 T[0] = build(1,n); 104 for(int i = 1; i <= cnt; i++) { 105 if(node[i].D > 0) 106 T[i] = update(T[i-1],rind[node[i].index],1,node[i].D); 107 else 108 T[i] = update(T[i-1],rind[node[i].index],-1,node[i].D); 109 } 110 int x,a,b,c; 111 long long pre = 1; 112 while(MM--) { 113 scanf("%d%d%d%d",&x,&a,&b,&c); 114 int id = 0; 115 int l = 1, r = cnt; 116 while(l <= r) { 117 int mid = (l+r)/2; 118 if(node[mid].x < x || (node[mid].x == x && node[mid].D > 0)) { 119 id = mid; 120 l = mid+1; 121 } else { 122 r = mid-1; 123 } 124 } 125 int K = (pre%c*a%c+b)%c; 126 if(K == 0) { 127 printf("0 "); 128 pre = 0; 129 continue; 130 } 131 long long ans = query(T[id],K); 132 if(pre > P)ans *= 2; 133 printf("%I64d ",ans); 134 pre = ans; 135 } 136 } 137 return 0; 138 }
Xor http://acm.hdu.edu.cn/showproblem.php?pid=4867
看不懂的。待补。
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 #define lson(x) ((x)<<1) 7 #define rson(x) ((x)<<1|1) 8 typedef long long LL ; 9 const int P = 1000000007 ; 10 const int MAXN = 10001 ; 11 const int MAXLEN = 220; 12 const int MAXM = 10 ; // 0<=x_i<2^30 13 typedef short Node; 14 typedef pair<short,int> CNode; 15 CNode M[ MAXN << 2 ][ MAXLEN ]; 16 int Mlen[ MAXN << 2 ]; 17 int ID[ MAXN ] ; 18 bool one[10]; 19 vector<short> ret; 20 vector<short> split(int n){ //将n化为二进制 ai<=1000 2^10=1024 so 10bit 21 for(int i=0;i<10;i++){ 22 one[i]=(n>>i)&1; //one 二进制逆序的 23 } 24 LL pre=0; 25 ret.clear(); 26 for(int i=9;i>=0;i--){ 27 pre<<=1; 28 if(one[i]){ 29 ret.push_back(pre<<4|i); //四位可以表示10 i<10 30 pre|=1; 31 } 32 } 33 ret.push_back(pre<<4); 34 return ret; 35 } 36 short llen ; 37 inline short merge( short a, short b ) { 38 short ra = a&0xf, rb=b&0xf; 39 short c=max( ra, rb); 40 llen = min(ra,rb); 41 a>>=4; 42 b>>=4; 43 a >>= (c-ra); 44 b >>= (c-rb); 45 return (a^b)<<4|c; 46 } 47 int a[ MAXN ]; 48 int max_size ; 49 CNode tM[ MAXLEN*MAXLEN]; 50 void merge( CNode a[], int alen, CNode b[], int blen, 51 CNode c[], int &k) { 52 k = 0; 53 int tlen = 0; 54 for( int i = 0; i < alen; ++ i) { 55 short pre = a[i].first, now ; 56 LL A = a[i].second; 57 for(int j = 0; j < blen; ++ j) { 58 now = merge( b[j].first, pre ); 59 int B = b[j].second; 60 tM[tlen ++] = make_pair( now, (A *(1<<llen)%P)*B%P); 61 } 62 } 63 sort( tM, tM + tlen ); 64 for(int i=0; i<tlen; ++i) { 65 if(!i || tM[i].first != tM[i-1].first) { 66 c[k++] = tM[i]; 67 } else c[k-1].second = (c[k-1].second + tM[i].second)%P; 68 } 69 } 70 int msz; 71 void build(int x, int l, int r) { 72 int m=(l+r)>>1; 73 Mlen[x] = 0; 74 if(l+1==r) { 75 ID[l]=x; 76 vector< Node > v=split( a[l] ); 77 for(int i = 0; i < v.size(); ++ i) M[ x ][ Mlen[x] ++ ] = make_pair(v[i],1); 78 msz=max(msz,Mlen[x]); 79 return ; 80 } 81 build( lson(x), l, m); 82 build( rson(x), m, r); 83 merge( M[lson(x)], Mlen[lson(x)], M[rson(x)], Mlen[rson(x)], M[x],Mlen[x]); 84 msz=max(msz,Mlen[x]); 85 } 86 void update( int pos, int val ) { 87 vector< Node > v=split( val); 88 a[pos ] =val ; 89 int x = ID[pos ]; 90 Mlen[ x ] = 0; 91 for(int i = 0; i < v.size(); ++ i) M[ x ][ Mlen[ x ] ++ ] = make_pair(v[i],1); 92 for(x >>= 1; x ; x >>= 1) { 93 merge( M[lson(x)], Mlen[lson(x)], M[rson(x)], Mlen[rson(x)], M[x],Mlen[x]); 94 } 95 } 96 int count( int k) { 97 LL ans = 0; 98 for(int i = 0; i < MAXM; ++ i) { 99 Node tar = k<<4|i; 100 int j = lower_bound( M[1], M[1] + Mlen[1], make_pair(tar, -1)) - M[1]; 101 if( j<Mlen[1] && M[1][j].first == tar) { 102 ans += M[ 1 ][ j].second; 103 ans %= P; 104 } 105 k >>= 1; 106 } 107 return (int) ans; 108 } 109 int main() { 110 int n, m,T; 111 cin >> T ; 112 while(T--) { 113 cin >> n >> m; 114 for(int i=0; i<n; ++i) scanf("%d", a + i); 115 build( 1, 0, n ); 116 for(int c=0; c<m; ++c) { 117 char op[ 4 ]; 118 int a, b; 119 scanf("%s", op); 120 if(op[0] == 'C') { 121 scanf("%d%d", &a, &b); 122 update( a, b ); 123 } else { 124 scanf("%d", &a); 125 printf("%d ", count(a) ); 126 } 127 } 128 } 129 return 0; 130 }
Information Extraction http://acm.hdu.edu.cn/showproblem.php?pid=4868
模拟题。没研究。
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 const int N=10010; 5 const int M=35; 6 char html[M][N],stored[M][N],sta1[N][M]; 7 char mapping[M][M][2][M]; 8 int mapNum[M],sta2[N]; 9 void getHTML(int n) { 10 int j,i=0,flag=1; 11 char beginTag[M],tag[M]; 12 getchar(); 13 while(1) { 14 html[n][i]=getchar(); 15 if(html[n][i]=='<') { 16 j=0; 17 while(html[n][++i]=getchar()) { 18 if(html[n][i]=='/')continue; 19 if(html[n][i]==' '||html[n][i]=='>')break; 20 tag[j++]=html[n][i]; 21 } 22 tag[j]='