2021.10.16(2)
T1:Makik的家
Problem:
一个夜晚一些旅行者想要过桥. 他们只有一个火把. 火把的亮光最多允许两个旅行者同时过桥. 没有火把或者多于 2 个人则不能过桥.每个旅行者过桥都需要特定的时间, 两个旅行者同时过桥时时间应该算较慢的那个. 我们想知道所有旅行者最少要花费多少时间才能全部过桥?
For Example:现在有 4 个人. 他们分别需要花费 6,7,10,15 分钟过桥.下面演示了他们如何使用 42 分钟全部过桥的。
1.熟练度为 6 的和熟练度为 7 的走
2.熟练度为 6 的乘车返回
3.熟练度为 15 的和熟练度为 10 的走
4.熟练度为 7 的返回
5.熟练度为 6 的和熟练度为 7 的走
共 7+6+15+7+7=42 分
现在 Makik 想知道他们共 n 个人通过高速公路的最短时间是多少呢?
Code:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=100100; 4 int n,a[maxn]; 5 long long f[maxn]; 6 int main(){ 7 int i; 8 cin>>n; 9 for(i=1;i<=n;i++) scanf("%d",&a[i]); 10 if(n<=2){ 11 cout<<a[n]<<endl; 12 return 0; 13 } 14 for(i=n-1;i>=2;i--){ 15 f[i]=f[i+1]+a[1]+a[i+1]; 16 if(i<=n-2) f[i]=min(f[i],f[i+2]+a[2]+a[1]+a[i+2]+a[2]); 17 } 18 cout<<f[2]+a[2]<<endl; 19 return 0; 20 }
T2:代码拍卖会
Problem:
随着 iPig 在 P++语言上的造诣日益提升,他形成了自己一套完整的代码库。猪王国想参加 POI 的童鞋们都争先恐后问 iPig 索要代码库。iPig 不想把代码库给所有想要的小猪,只想给其中的一部分既关系好又肯出钱的小猪,于是他决定举行了一个超大型拍卖会。
在拍卖会上,所有的 N 头小猪将会按照和 iPig 的好感度从低到高,从左到右地在 iPig面前站成一排。每个小猪身上都有 9 猪币(与人民币汇率不明),从最左边开始,每个小猪依次举起一块牌子,上面写上想付出的买代码库的猪币数量(1 到 9 之间的一个整数)。大家都知道,如果自己付的钱比左边的猪少,肯定得不到梦寐以求的代码库,因此从第二只起,每只猪出的钱都大于等于左边猪出的价钱。最终出的钱最多的小猪(们)会得到 iPig 的代
码库真传,向着保送 PKU(Pig Kingdom University)的梦想前进。
iPig 对自己想到的这个点子感到十分满意,在去现场的路上,iPig 就在想象拍卖会上会出现的场景,例如一共会出现多少种出价情况之类的问题,但这些问题都太简单了,iPig早已不敢兴趣了,他想要去研究更加困难的问题。iPig 发现如果他从台上往下看,所有小猪举的牌子从左到右将会正好构成一个 N 位的整数,他现在想要挑战的问题是所有可能构成的整数中能正好被 P 整除的有多少个。由于答案过大,他只想要知道答案 mod 999911659
就行了。
Code:
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const ll base=999911659; 5 ll dp[501][501][9]; 6 ll cnt[501]; 7 ll mod[2000]; 8 ll i,j,k,l,t,l1,l2,r,ans; 9 ll mem[501][9]; 10 ll ext_gcd(ll a,ll b,ll &x,ll &y){ 11 if(b==0){ 12 x=1; 13 y=0; 14 return a; 15 } 16 ll res=ext_gcd(b,a%b,x,y); 17 ll tmp=x; 18 x=y; 19 y=tmp-a/b*y; 20 return res; 21 } 22 ll c(ll m,int n){ 23 ll res=1; 24 for(ll i=1;i<=n;i++){ 25 res=((m-i+1)%base)*res%base; 26 ll x,y; 27 ext_gcd(i,base,x,y); 28 res=((res*x)%base+base)%base; 29 } 30 return res; 31 } 32 int solve(ll n,int p){ 33 memset(cnt,0,sizeof(cnt)); 34 memset(dp,0,sizeof(dp)); 35 t=1%p; 36 cnt[t]=1; 37 mod[1]=t; 38 for(i=2;;i++){ 39 t=(t*10+1)%p; 40 if(cnt[t]==0){ 41 cnt[t]=i; 42 mod[i]=t; 43 } 44 else{ 45 l1=cnt[t]-1; 46 l2=i-cnt[t]; 47 break; 48 } 49 } 50 memset(cnt,0,sizeof(cnt)); 51 for(i=1;i<=l1&&i<=n;i++) cnt[mod[i]]=1; 52 if(n>l1){ 53 for(i=l1+1;i<=l1+l2;i++){ 54 if(i-l1-1<(n-l1)%l2) cnt[mod[i]]=(n-l1)/l2+1; 55 else cnt[mod[i]]=(n-l1)/l2; 56 } 57 } 58 if(n<=l1) r=mod[n]; 59 else r=mod[(n-l1-1)%l2+l1+1]; 60 r=(p-r)%p; 61 for(i=0;i<p;i++){ 62 if(cnt[i]>0){ 63 for(j=0;j<=8;j++) mem[i][j]=c(cnt[i]+j-1,j); 64 } 65 } 66 dp[0][0][0]=1; 67 if(cnt[0]>0) for(k=1;k<=8;k++) dp[0][0][k]=mem[0][k]; 68 for(i=1;i<p;i++){ 69 if(cnt[i]==0){ 70 for(j=0;j<p;j++) for(k=0;k<=8;k++) dp[i][j][k]=dp[i-1][j][k]; 71 } 72 else{ 73 for(j=0;j<p;j++){ 74 for(k=0;k<=8;k++){ 75 for(l=0;k+l<=8;l++){ 76 dp[i][(j+i*l)%p][k+l]=(dp[i][(j+i*l)%p][k+l]+dp[i-1][j][k]*mem[i][l])%base; 77 } 78 } 79 } 80 } 81 } 82 ans=0; 83 for(k=0;k<=8;k++) ans=(ans+dp[p-1][r][k])%base; 84 return ans; 85 } 86 int main(){ 87 ll n; 88 int p; 89 cin>>n>>p; 90 cout<<solve(n,p)<<endl; 91 return 0; 92 }
T3:Makik的动态树
Problem:
Makik 今日自己发明了一个动态树,不同于众所周知的动态树 LCT,Makik 这个树有 n 个节点,每个节点都有一个点权。而之所以是动态是因为过程中会对点权发生修改,更准确的说,每次都会让某个点的点权增加一个非负整数。
同时,有时会进行询问的操作:询问某棵子树中所有叶子节点到达根节点的路径上至少有一个节点被选择的最少总代价是多少?请你帮助 Makik 维护这个动态树。
Code:
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int maxn=200010; 5 int n,m,cnt,to[maxn<<1],nxt[maxn<<1],head[maxn],p[maxn]; 6 int Q[maxn],dep[maxn],fa[maxn],top[maxn],siz[maxn],son[maxn]; 7 char str[5]; 8 ll sv[maxn<<2],ts[maxn<<2],sc[maxn<<2],v[maxn],g[maxn]; 9 inline void add(int a,int b){ 10 to[cnt]=b; 11 nxt[cnt]=head[a]; 12 head[a]=cnt++; 13 } 14 void dfs1(int x){ 15 siz[x]=1; 16 for(int i=head[x];i!=-1;i=nxt[i]){ 17 if(to[i]!=fa[x]){ 18 fa[to[i]]=x; 19 dep[to[i]]=dep[x]+1; 20 dfs1(to[i]); 21 siz[x]+=siz[to[i]]; 22 if(siz[to[i]]>siz[son[x]]) son[x]=to[i]; 23 g[x]+=min(g[to[i]],v[to[i]]); 24 } 25 } 26 if(siz[x]==1) g[x]=1<<30; 27 } 28 void dfs2(int x,int tp){ 29 p[x]=++p[0]; 30 Q[p[0]]=x; 31 top[x]=tp; 32 if(son[x]) dfs2(son[x],tp); 33 for(int i=head[x];i!=-1;i=nxt[i]){ 34 if(to[i]!=fa[x]&&to[i]!=son[x]) dfs2(to[i],to[i]); 35 } 36 } 37 inline void pushdown(int x){ 38 if(ts[x]){ 39 sc[x<<1]-=ts[x]; 40 sc[x<<1|1]-=ts[x]; 41 ts[x<<1]+=ts[x]; 42 ts[x<<1|1]+=ts[x]; 43 ts[x]=0; 44 } 45 } 46 void build(int l,int r,int x){ 47 if(l==r){ 48 sv[x]=v[Q[l]]; 49 sc[x]=v[Q[l]]-g[Q[l]]; 50 return ; 51 } 52 int mid=(l+r)>>1; 53 build(l,mid,x<<1); 54 build(mid+1,r,x<<1|1); 55 sv[x]=min(sv[x<<1],sv[x<<1|1]); 56 sc[x]=min(sc[x<<1],sc[x<<1|1]); 57 } 58 ll getg(int l,int r,int x,int a){ 59 if(l==r) return sv[x]-sc[x]; 60 pushdown(x); 61 int mid=(l+r)>>1; 62 if(a<=mid) return getg(l,mid,x<<1,a); 63 return getg(mid+1,r,x<<1|1,a); 64 } 65 ll getv(int l,int r,int x,int a,int b){ 66 if(l==r) return sv[x]; 67 pushdown(x); 68 int mid=(l+r)>>1; 69 if(b<=mid) return getv(l,mid,x<<1,a,b); 70 if(a>mid) return getv(mid+1,r,x<<1|1,a,b); 71 return min(getv(l,mid,x<<1,a,b),getv(mid+1,r,x<<1|1,a,b)); 72 } 73 ll getc(int l,int r,int x,int a,int b){ 74 if(a<=l&&r<=b) return sc[x]; 75 pushdown(x); 76 int mid=(l+r)>>1; 77 if(b<=mid) return getc(l,mid,x<<1,a,b); 78 if(a>mid) return getc(mid+1,r,x<<1|1,a,b); 79 return min(getc(l,mid,x<<1,a,b),getc(mid+1,r,x<<1|1,a,b)); 80 } 81 void upg(int l,int r,int x,int a,int b,ll c){ 82 if(a<=l&&r<=b){ 83 if(c==-1){ 84 sc[x]+=v[Q[l]]-sv[x]; 85 sv[x]=v[Q[l]]; 86 } 87 else{ 88 sc[x]-=c; 89 ts[x]+=c; 90 } 91 return ; 92 } 93 pushdown(x); 94 int mid=(l+r)>>1; 95 if(a<=mid) upg(l,mid,x<<1,a,b,c); 96 if(b>mid) upg(mid+1,r,x<<1|1,a,b,c); 97 sv[x]=min(sv[x<<1],sv[x<<1|1]); 98 sc[x]=min(sc[x<<1],sc[x<<1|1]); 99 } 100 inline void change(int x,ll d){ 101 while(x){ 102 ll gx=getg(1,n,1,p[x]),fx=min(gx,v[x]); 103 upg(1,n,1,p[x],p[x],d); 104 if(gx>=v[x]) return ; 105 if(gx+d>v[x]){ 106 d=v[x]-fx; 107 x=fa[x]; 108 } 109 else{ 110 if(top[x]==x) x=fa[x]; 111 else if(getc(1,n,1,p[top[x]],p[x]-1)>=d){ 112 upg(1,n,1,p[top[x]],p[x]-1,d); 113 x=fa[top[x]]; 114 } 115 else{ 116 int l=p[top[x]],r=p[x],mid; 117 while(l<r){ 118 mid=(l+r)>>1; 119 if(getc(1,n,1,mid,p[x]-1)>=d) r=mid; 120 else l=mid+1; 121 } 122 if(r<p[x]) upg(1,n,1,r,p[x]-1,d); 123 x=Q[r-1]; 124 } 125 } 126 } 127 } 128 int main(){ 129 scanf("%d",&n); 130 int i,a,b; 131 for(i=1;i<=n;i++) scanf("%d",&v[i]); 132 memset(head,-1,sizeof(head)); 133 for(i=1;i<n;i++){ 134 scanf("%d%d",&a,&b); 135 add(a,b); 136 add(b,a); 137 } 138 dep[1]=1; 139 dfs1(1); 140 dfs2(1,1); 141 scanf("%d",&m); 142 build(1,n,1); 143 for(i=1;i<=m;i++){ 144 scanf("%s",str); 145 if(str[0]=='C'){ 146 scanf("%d%d",&a,&b); 147 ll gx=getg(1,n,1,p[a]),fx=min(gx,v[a]); 148 v[a]+=b; 149 upg(1,n,1,p[a],p[a],-1); 150 if(min(v[a],gx)>fx) change(fa[a],min(v[a],gx)-fx); 151 } 152 else{ 153 scanf("%d",&a); 154 printf("%lld\n",min(v[a],getg(1,n,1,p[a]))); 155 } 156 } 157 return 0; 158 }