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 }
posted @ 2021-10-16 21:12  B_lank  阅读(34)  评论(0编辑  收藏  举报