[校内训练20_01_17]ABC

1.平面上每次加入直角边平行于坐标轴的等腰直角三角形,每次询问某个点被覆盖了多少次。

大常数算法:O(nlog^2)

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=3E5+5; 
  4 int n,q;
  5 inline int read()
  6 {
  7     char ch=getchar();
  8     while(!isdigit(ch))ch=getchar();
  9     int x=ch-'0';
 10     ch=getchar();
 11     while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
 12     return x;
 13 }
 14 int G[55];
 15 inline void write(int x)
 16 {
 17     int g=0;
 18     do{G[++g]=x%10;x/=10;}while(x);
 19     for(int i=g;i>=1;--i)putchar(G[i]+'0');putchar('
');
 20 }
 21 //////////////////////////////////////////////////////////////////////////////////////// splay
 22 int t[10000000],fa[10000000],val[10000000],sum[10000000],son[10000000][2],cnt[10000000],TOT;
 23 struct Splay
 24 {
 25     int root;
 26     inline void update(int x)
 27     {
 28         sum[x]=sum[son[x][0]]+sum[son[x][1]]+cnt[x];
 29     }
 30     inline void rotate(int x)
 31     {
 32         int y=fa[x];
 33         int c=son[y][0]==x;
 34         fa[x]=fa[y];
 35         son[y][!c]=son[x][c];
 36         if(son[x][c])
 37             fa[son[x][c]]=y;
 38         if(son[fa[y]][0]==y)
 39             son[fa[y]][0]=x;
 40         else
 41             son[fa[y]][1]=x;
 42         son[x][c]=y;
 43         fa[y]=x;
 44         update(y);
 45         update(x);
 46         if(y==root)
 47             root=x;
 48     }
 49     inline void splay(int x)
 50     {
 51         if(x==root)
 52             return;
 53         while(true)
 54         {
 55             int y=fa[x];
 56             if(y==0)
 57                 break;
 58             if(y==root)
 59             {
 60                 rotate(x);
 61                 break;
 62             }
 63             if((son[fa[y]][0]==y)==(son[y][0]==x))
 64                 rotate(y),rotate(x);
 65             else
 66                 rotate(x),rotate(x);
 67         }
 68     }
 69     inline void insert(int x)
 70     {
 71         if(root==0)
 72         {
 73             root=++TOT;
 74             sum[root]=cnt[root]=1;
 75             val[root]=x;
 76             return;
 77         }
 78         int pos=root;
 79         while(true)
 80         {
 81             ++sum[pos];
 82             if(val[pos]==x)
 83             {
 84                 ++cnt[pos];
 85                 break;
 86             }
 87             if(x<val[pos])
 88             {
 89                 if(son[pos][0]==0)
 90                 {
 91                     son[pos][0]=++TOT;
 92                     sum[TOT]=cnt[TOT]=1;
 93                     val[TOT]=x;
 94                     fa[TOT]=pos;
 95                     break;
 96                 }
 97                 pos=son[pos][0];
 98             }
 99             else
100             {
101                 if(son[pos][1]==0)
102                 {
103                     son[pos][1]=++TOT;
104                     sum[TOT]=cnt[TOT]=1;
105                     val[TOT]=x;
106                     fa[TOT]=pos;
107                     break;
108                 }
109                 pos=son[pos][1];
110             }
111         }
112 //        splay(pos);
113     }
114     inline int askSmaller(int x)// how many numbers are <= x
115     {
116         int ans=0;
117         int pos=root;
118         while(pos)
119         {
120             if(x<val[pos])
121                 pos=son[pos][0];
122             else
123             {
124                 ans+=sum[son[pos][0]]+cnt[pos];
125                 pos=son[pos][1];
126             }
127         }
128         return ans;
129     }
130     inline int askBigger(int x)// how many numbers are >= x
131     {
132         int ans=0;
133         int pos=root;
134         while(pos)
135         {
136             if(x>val[pos])
137                 pos=son[pos][1];
138             else
139             {
140                 ans+=sum[son[pos][1]]+cnt[pos];
141                 pos=son[pos][0];
142             }
143         }
144         return ans;
145     }
146     void out()
147     {
148         cout<<root<<endl;
149         cout<<"FA   :";for(int i=1;i<=TOT;++i)cout<<fa[i]<<" ";cout<<endl;
150         cout<<"SUM  :";for(int i=1;i<=TOT;++i)cout<<sum[i]<<" ";cout<<endl;
151         cout<<"VAl  :";for(int i=1;i<=TOT;++i)cout<<val[i]<<" ";cout<<endl;
152         cout<<"SON  :";for(int i=1;i<=TOT;++i)cout<<son[i][0]<<" ";cout<<endl;
153         cout<<"     :";for(int i=1;i<=TOT;++i)cout<<son[i][1]<<" ";cout<<endl;
154     }
155 };
156 ////////////////////////////////////////////////////////////////////////////////////////
157 struct Segment
158 {
159     Splay T[maxn*4];
160     inline void add(int L,int R,int l,int r,int x,int num)
161     {
162         if(L<=l&&r<=R)
163         {
164             T[num].insert(x);
165             return;
166         }
167         int mid=(l+r)>>1;
168         if(R<=mid)
169             add(L,R,l,mid,x,num<<1);
170         else if(mid<L)
171             add(L,R,mid+1,r,x,num<<1|1);
172         else
173             add(L,R,l,mid,x,num<<1),add(L,R,mid+1,r,x,num<<1|1);
174     }
175     inline int askSmaller(int l,int r,int pos,int x,int num)// <=
176     {
177         if(l==r)
178             return T[num].askSmaller(x);
179         int mid=(l+r)>>1;
180         if(pos<=mid)
181             return askSmaller(l,mid,pos,x,num<<1)+T[num].askSmaller(x);
182         else
183             return askSmaller(mid+1,r,pos,x,num<<1|1)+T[num].askSmaller(x);
184     }
185     inline int askBigger(int l,int r,int pos,int x,int num)// >=
186     {
187         if(l==r)
188             return T[num].askBigger(x);
189         int mid=(l+r)>>1;
190         if(pos<=mid)
191             return askBigger(l,mid,pos,x,num<<1)+T[num].askBigger(x);
192         else
193             return askBigger(mid+1,r,pos,x,num<<1|1)+T[num].askBigger(x);
194     }
195 }T[8];
196 int main()
197 {
198     freopen("frontier.in","r",stdin);
199     freopen("frontier.out","w",stdout);
200     ios::sync_with_stdio(false);
201     int useless=read();
202     n=read(),q=read();
203     while(q--)
204     {
205         int opt=read();
206         if(opt==1)
207         {
208             opt=read();
209             int x=read(),y=read(),z=read();
210             if(opt==1)
211             {
212                 T[0].add(y,y+z,1,n,x+y+z,1);
213                 T[1].add(y,y+z,1,n,x-1,1);
214             }
215             else if(opt==2)
216             {
217                 T[2].add(y-z,y,1,n,x-(y-z),1);
218                 T[1].add(y-z,y,1,n,x-1,1);
219             }
220             else if(opt==3)
221             {
222                 T[4].add(y,y+z,1,n,x-(y+z),1);
223                 T[5].add(y,y+z,1,n,x+1,1);
224             }
225             else
226             {
227                 T[6].add(y-z,y,1,n,x+y-z,1);
228                 T[5].add(y-z,y,1,n,x+1,1);
229             }
230         }
231         else
232         {
233             int x=read(),y=read();
234             int ans1=T[0].askBigger(1,n,y,x+y,1)-T[1].askBigger(1,n,y,x,1);
235             int ans2=T[2].askBigger(1,n,y,x-y,1);
236             int ans3=T[4].askSmaller(1,n,y,x-y,1)-T[5].askSmaller(1,n,y,x,1);
237             int ans4=T[6].askSmaller(1,n,y,x+y,1);
238             write(ans1+ans2+ans3+ans4);
239         }
240     }
241     return 0;
242 }
View Code

离线做法:还没写


2.

    小L 的治疗总共分为N 个阶段,在第i 个阶段,小L 可以做出如下选择:
    1.施放治愈法术,为永恒之树恢复xi + S 点生命力
    2.为法杖注入能量,令法术强度S 增加yi
    3.吟唱圣歌,召唤zi只木精灵
    在每个阶段结束时,每只木精灵会使得法术强度S增加1
    请帮助小L 计算在N个阶段结束后,能够为永恒之树恢复的最大生命力。
n <= 80

简单题。n^4

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long int ll;
 4 const ll inf=1E15;
 5 ll f[85][85][85*85];
 6 ll n,a[85],b[85],c[85];
 7 inline ll max(ll x,ll y)
 8 {
 9     return x>y?x:y;
10 }
11 inline void U(ll&x,ll y)
12 {
13     x=max(x,y);
14 }
15 inline void solve()
16 {
17     cin>>n;
18     for(
19     int i=1;i<=n;++i)
20         cin>>a[i]>>b[i]>>c[i];
21     for(int i=0;i<=n;++i)
22         for(int j=0;j<=n;++j)
23             for(int k=0;k<=n*n;++k)
24                 f[i][j][k]=-inf;
25     f[n][0][0]=0;
26     f[n][1][0]=a[n];
27     for(int i=n;i>=2;--i)
28     {
29         for(int j=0;j<=n;++j)
30         {
31             for(int k=0;k<=n*n;++k)
32             {
33                 U(f[i-1][j+1][j+k],f[i][j][k]+a[i-1]);
34                 U(f[i-1][j][j+k],f[i][j][k]+b[i-1]*j);
35                 U(f[i-1][j][j+k],f[i][j][k]+c[i-1]*(j+k));
36             }
37         }
38     }
39     ll ans=0;
40     for(int i=1;i<=n;++i)
41         for(int j=0;j<=n*n;++j)
42             ans=max(ans,f[1][i][j]);
43     cout<<ans<<endl;
44 }
45 int main()
46 {
47     freopen("fortune.in","r",stdin);
48     freopen("fortune.out","w",stdout);
49     ios::sync_with_stdio(false);
50     int useless,T;
51     cin>>useless>>T;
52     while(T--)
53         solve();
54     return 0;
55 }
View Code

3.

    在小L 的努力下,永恒之树已经恢复了生命力。
    渐渐恢复元气的X 国将进行一次占卜仪式,在仪式中,小L 将取下一段永恒之树的树枝。这里,我们将一段树枝抽象成
一张N个点,M 条边的无向图,恢复了生命力的永恒之树已经脱离了普通的树的范畴,但仍然具备一些树的特性,譬如每条边
都只在至多一个简单环中出现。
    小L 将对取下的树枝使用分解魔法,此后,树枝的每一个节点都会在一个时辰内随机的一个时刻,连同其连出去的边一
起被分解。在被分解的瞬间,每个节点会释放出等同于当时还与其连通的节点数量的能量,将这些能量求和,便得到了X 国的
气运。
    现在,小L 想要知道,X 国的气运期望会是多少。
    请求出X 国气运的期望对998244353 取模的结果。

  

  

即求一个仙人掌随机点分治的期望复杂度。

若仙人掌是一棵树,考虑一对点之间的贡献。即x对y产生贡献,即x在被选中前始终与y联通的概率,为$frac{1}{dist(x,y)}$,dist为两点之间的点的个数。

原文地址:https://www.cnblogs.com/GreenDuck/p/12205575.html