7.16训练 2013ACM-ICPC杭州全国邀请赛
我写了A和G,G似乎是一道通过率比较低的题目,数据结构C没写出来。
总共过了4题
A
一个机器人在长度为n的环上,有m个指令,发出后机器人随机顺时针或逆时针走若干步,问最终机器人落在一个区间的概率。
n<=200 m<=10^6
题解:
简单概率DP,但是卡时间和空间。
4000ms时限,3900ms通过。
很难让人不怀疑有其他做法(事实上确实想到了O(n^3+m)的做法,但是有精度限制,如果可以对概率取模,就能做了
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 double f[2][201],g[500]; 4 int main() 5 { 6 int n,m,l,r; 7 while (1) 8 { 9 scanf("%d%d%d%d",&n,&m,&l,&r); 10 if (n==0&&m==0&&l==0&&r==0) break; 11 f[0][1]=1; 12 for (int i=1;i<=n;i++) g[i]=0; 13 int w=1; 14 for (int i=1;i<=m;i++) 15 { 16 int x; 17 scanf("%d",&x); 18 for (int j=1;j<=n;j++) 19 { 20 int k1=(j+x-1)%n+1; 21 int k2=(j+(n-x)-1)%n+1; 22 f[w][j]=f[1-w][k1]*0.5+f[1-w][k2]*0.5; 23 } 24 w=1-w; 25 } 26 double ans=0; 27 for (int i=l;i<=r;i++) ans+=f[m&1][i]; 28 for (int j=1;j<=n;j++) f[0][j]=0; 29 printf("%.4lf\n",ans); 30 } 31 32 }
G
给一棵图的dfs树和一些不在dfs树上的边,定义简单环为只有一条边不在树上的环,选出一些树边,使得原图中所有简单环都至少被选中一条边。
n<=2000 m<=20000
题解:
一个图取出dfs树之后,除了树边,只剩下返祖边。
单独考虑一条从根到叶子的路径,可以从树上退化下来,就是一个点覆盖区间问题,上树之后做法也是差不多的。
值得吐槽的是,数据有重边...这很令人难受。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=2e3+10; 4 const int M=4e4+10; 5 int tot=0,tot1=0,ans=0,n,tt=0; 6 int he[N],ne[M],t[M]; 7 int he1[N],ne1[M],t1[M]; 8 int a[M],b[M]; 9 int dep[N],f[N]; 10 int pp[N][N]; 11 void link(int x,int y) 12 { 13 tot++; 14 ne[tot]=he[x]; 15 he[x]=tot; 16 t[tot]=y; 17 } 18 void link1(int x,int y) 19 { 20 tot1++; 21 ne1[tot1]=he1[x]; 22 he1[x]=tot1; 23 t1[tot1]=y; 24 } 25 void dfs(int x,int y) 26 { 27 dep[x]=dep[y]+1; 28 for (int i=he1[x];i;i=ne1[i]) if (t1[i]!=y) dfs(t1[i],x); 29 } 30 void dfs1(int x,int y) 31 { 32 for (int i=he1[x];i;i=ne1[i]) if (dep[t1[i]]==dep[x]+1&&t1[i]!=y) 33 { 34 dfs1(t1[i],x); 35 f[x]=max(f[x],f[t1[i]]); 36 } 37 if (f[x]+1==dep[x]&&f[x]) 38 { 39 ans++; 40 f[x]=0; 41 } 42 } 43 int main() 44 { 45 int m; 46 while (1) 47 { 48 scanf("%d%d",&n,&m); 49 tt++; 50 if (n==0&&m==0) break; 51 for (int i=1;i<=n;i++) he[i]=he1[i]=0,f[i]=0,dep[i]=0; 52 tot=tot1=0; 53 for (int i=1;i<n;i++) 54 { 55 int x,y; 56 scanf("%d%d",&x,&y); 57 link1(x,y); 58 link1(y,x); 59 } 60 dfs(1,0); 61 for (int i=n;i<=m;i++) 62 { 63 scanf("%d%d",&a[i],&b[i]); 64 if (dep[a[i]]<dep[b[i]]) swap(a[i],b[i]); 65 if (abs(dep[a[i]]-dep[b[i]])!=1) f[a[i]]=max(f[a[i]],dep[b[i]]); 66 } 67 ans=0; 68 dfs1(1,0); 69 //if (f[1]==1) ans++; 70 printf("%d\n",ans); 71 } 72 }
补题:
C
三个操作:区间加,区间乘,区间赋值
三种询问:区间和,区间平方和,区间立方和
n<=10^5 m<=10^5
题解:
打三种标记,标记有等级,赋值标记为最高级,影响另外两种标记。
乘标记为次高级,影响加标记。
线段树即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10; 4 const int mo=1e4+7; 5 int s[4][N*4],b1[N*4],b2[N*4],b3[N*4]; 6 void build(int rt,int l,int r) 7 { 8 s[1][rt]=s[2][rt]=s[3][rt]=b1[rt]=b3[rt]=0; 9 b2[rt]=1; 10 if (l==r) return; 11 int mid=l+r>>1; 12 build(rt<<1,l,mid); 13 build(rt<<1|1,mid+1,r); 14 } 15 void up(int rt) 16 { 17 s[1][rt]=(s[1][rt<<1]+s[1][rt<<1|1])%mo; 18 s[2][rt]=(s[2][rt<<1]+s[2][rt<<1|1])%mo; 19 s[3][rt]=(s[3][rt<<1]+s[3][rt<<1|1])%mo; 20 } 21 void c1(int rt,int l,int r,int c) 22 { 23 s[3][rt]=(s[3][rt]+3*s[1][rt]%mo*c%mo*c%mo+3*s[2][rt]%mo*c%mo+1ll*(r-l+1)*c%mo*c%mo*c%mo)%mo; 24 s[2][rt]=(s[2][rt]+2*s[1][rt]%mo*c%mo+1ll*(r-l+1)*c%mo*c%mo)%mo; 25 s[1][rt]=(s[1][rt]+1ll*(r-l+1)*c%mo)%mo; 26 b1[rt]=(b1[rt]+c)%mo; 27 } 28 void c2(int rt,int l,int r,int c) 29 { 30 s[3][rt]=s[3][rt]*c%mo*c%mo*c%mo; 31 s[2][rt]=s[2][rt]*c%mo*c%mo; 32 s[1][rt]=s[1][rt]*c%mo; 33 b1[rt]=b1[rt]*c%mo; 34 b2[rt]=b2[rt]*c%mo; 35 } 36 void c3(int rt,int l,int r,int c) 37 { 38 s[3][rt]=1ll*c*c%mo*c%mo*(r-l+1)%mo; 39 s[2][rt]=1ll*c*c%mo*(r-l+1)%mo; 40 s[1][rt]=1ll*c*(r-l+1)%mo; 41 b1[rt]=0; 42 b2[rt]=1; 43 b3[rt]=c; 44 } 45 void push(int rt,int l,int r) 46 { 47 int mid=l+r>>1; 48 if (b3[rt]) 49 { 50 c3(rt<<1,l,mid,b3[rt]); 51 c3(rt<<1|1,mid+1,r,b3[rt]); 52 b3[rt]=0; 53 } 54 if (b2[rt]!=1) 55 { 56 c2(rt<<1,l,mid,b2[rt]); 57 c2(rt<<1|1,mid+1,r,b2[rt]); 58 b2[rt]=1; 59 } 60 if (b1[rt]) 61 { 62 c1(rt<<1,l,mid,b1[rt]); 63 c1(rt<<1|1,mid+1,r,b1[rt]); 64 b1[rt]=0; 65 } 66 } 67 void m1(int rt,int l,int r,int x,int y,int z) 68 { 69 if (l>=x&&r<=y) 70 { 71 c1(rt,l,r,z); 72 return; 73 } 74 push(rt,l,r); 75 int mid=l+r>>1; 76 if (x<=mid) m1(rt<<1,l,mid,x,y,z); 77 if (y>mid) m1(rt<<1|1,mid+1,r,x,y,z); 78 up(rt); 79 } 80 void m2(int rt,int l,int r,int x,int y,int z) 81 { 82 if (l>=x&&r<=y) 83 { 84 c2(rt,l,r,z); 85 return; 86 } 87 push(rt,l,r); 88 int mid=l+r>>1; 89 if (x<=mid) m2(rt<<1,l,mid,x,y,z); 90 if (y>mid) m2(rt<<1|1,mid+1,r,x,y,z); 91 up(rt); 92 } 93 void m3(int rt,int l,int r,int x,int y,int z) 94 { 95 if (l>=x&&r<=y) 96 { 97 c3(rt,l,r,z); 98 return; 99 } 100 push(rt,l,r); 101 int mid=l+r>>1; 102 if (x<=mid) m3(rt<<1,l,mid,x,y,z); 103 if (y>mid) m3(rt<<1|1,mid+1,r,x,y,z); 104 up(rt); 105 } 106 int qq(int rt,int l,int r,int x,int y,int z) 107 { 108 if (l>=x&&r<=y) return s[z][rt]; 109 push(rt,l,r); 110 int mid=l+r>>1,ret=0; 111 if (x<=mid) ret=ret+qq(rt<<1,l,mid,x,y,z); 112 if (y>mid) ret=ret+qq(rt<<1|1,mid+1,r,x,y,z); 113 return ret%mo; 114 } 115 int main() 116 { 117 int n,m; 118 while (1) 119 { 120 scanf("%d%d",&n,&m); 121 if (n==0&&m==0) break; 122 build(1,1,n); 123 for (int i=1;i<=m;i++) 124 { 125 int tp,l,r,x; 126 scanf("%d%d%d%d",&tp,&l,&r,&x); 127 if (tp==1) m1(1,1,n,l,r,x); 128 else if (tp==2) m2(1,1,n,l,r,x); 129 else if (tp==3) m3(1,1,n,l,r,x); 130 else printf("%d\n",qq(1,1,n,l,r,x)%mo); 131 } 132 } 133 }

浙公网安备 33010602011771号