Wannafly挑战赛13
A题模拟
B题等价于有n^2 -1个白球 1个黑球 摸出来m个摸到黑球的概率 组合数学搞搞
C题我猜了下,就是1到n行 每行加0,1,2,...n-1 每列加1,n+1,2n+1.....n^2-n+1是一种可行解 然后两边全排列的情况也行,然后交换行列的位置也行,所以是2*(p!)^2
D题切一个蛋糕肯定是均匀切划算,因为不均匀切这一刀就会贡献质量差,然后就是找到最大的蛋糕,对它多切一刀看行不行模拟。
E题先把线段按右端点排序,能与当前线段产生异或最大的会排在前面,我们就从左到右处理,首先对于当前处理的线段l,r先二分出之前线段的r在当前线段的[l,r]之间的范围,然后就是查询这个范围的线段的l+r,与l-r ,画一画就知道了。
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
const int maxn = 2e5+9;
struct line{
int l,r;
bool operator <(line a)const{
return r<a.r;
}
}l[maxn];
const int inf = 0x3f3f3f3f;
struct Node{
int p[2];
}node[maxn<<2];
void build(int l,int r,int root){
if(l==r){
node[root].p[0] = inf;
node[root].p[1] = -inf;
return ;
}
int mid=l+r>>1;
build(l,mid,root<<1);
build(mid+1,r,root<<1|1);
}
void pushup(int root){
node[root].p[0] =min(node[root<<1].p[0],node[root<<1|1].p[0]);
node[root].p[1] =max(node[root<<1].p[1],node[root<<1|1].p[1]);
}
void update(int l,int r,int root,int pos,int p0,int p1){
if(l==r){
node[root].p[0] = p0;
node[root].p[1] = p1;
return;
}
int mid=l+r>>1;
if(pos<=mid) update(l, mid, root<<1, pos, p0, p1);
else update(mid+1, r, root<<1|1, pos, p0, p1);
pushup(root);
}
int ql,qr;
int pp0,pp1;
void query(int l,int r,int root){
if(ql<=l && r<=qr) {
pp0 = min(pp0,node[root].p[0]);
pp1 = max(pp1,node[root].p[1]);
return ;
}
int mid=l+r>>1;
if(qr<=mid) {
query(l, mid, root<<1);
}else if(ql>mid) {
query(mid+1, r,root<<1|1);
}else {
query(l, mid, root<<1);
query(mid+1, r, root<<1|1);
}
}
int bs(int ll,int rr,int val){
int ans = rr;
while (ll<=rr) {
int mid=ll+rr>>1;
if(l[mid].r>=val){
rr=mid-1;
ans = mid;
}else{
ll = mid+1;
}
}
return ans;
}
int main(int argc, const char * argv[]) {
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&l[i].l,&l[i].r);
}
sort(l+1,l+1+n);
build(1,n,1);
int anss = 0;
for(int i=1;i<=n;i++){
update(1, n, 1, i, l[i].l+l[i].r,l[i].l-l[i].r);
qr = i;
ql = bs(1,i,l[i].l);
pp0 = inf;
pp1 = -inf;
query(1, n, 1);
anss = max(anss,l[i].l+l[i].r-pp0);
anss = max(anss,l[i].r-l[i].l+pp1);
}
printf("%d\n",anss);
return 0;
}
F题,主要思路就是通过对可爱值的分块,优化q^2的大暴力,首先我们可以在n+q的时间内处理Q个修改对n个点的影响,然后我们也有O(1)的算法解决已知u,v路径上被放了花,然后任意一点到这路径花的距离和,然后我门就可以把询问分块,分成q/N块,对于新来的询问,我们放进去询问中,如果询问是N的倍数,我们就重构之前所有的询问,每块重新维护的复杂度是n 然后一共有q/N块,重构的次数不会超过q/N次,反正就十分血腥暴力。
主要学到了把dfs改成了非递归的形式,还有树上差分的玩法(该点的真实值等于其所有子节点的差分数组和),好好写了一遍RMQ-LCA,log2打表的正确姿势,还有auto关键字玩lambda表达式,inplace_merge原地归并(暴力重构),还有lower_bound和upper_bound的手动实现和std玩法(感受到了前开后闭区间的优越性)。
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
typedef long long int ll;
/*
1.实现RMQ-LCA
*/
const int maxn = 1e5+9;
const int S = 800;
const int N = maxn/S+5;
const int K = 18;
ll VAL[N][maxn];
struct query{
int u,v,x;
}Q[maxn];
vector<int> vv[maxn];
int dep[maxn];
int ST_table[18][maxn<<1],first[maxn],dfsv[maxn],father[maxn];
int stcnt,dfscnt;
int Log2[maxn<<1];
ll qz[maxn];
void dfs(int now,int fa){
ST_table[0][++stcnt] = now;
first[now] = stcnt;
dfsv[++dfscnt] = now;
for(auto v:vv[now]) if(fa != v){
dep[v] = dep[now]+1;
father[v] = now;
dfs(v, now);
ST_table[0][++stcnt] = now;
}
}
inline int depmin(int u,int v){
return dep[u]<dep[v]?u:v;
}
void ST_init(){
for(int i=1;i<18;i++){
for(int j=1;j+(1<<(i-1))<=stcnt;j++){
ST_table[i][j] = depmin(ST_table[i-1][j],ST_table[i-1][j+(1<<(i-1))]);
}
}
}
inline int lca(int u,int v){
int posu = first[u];
int posv = first[v];
if(posu>posv) swap(posu,posv);
int step = Log2[posv-posu+1];
return depmin(ST_table[step][posu],ST_table[step][posv-(1<<step)+1]);
}
inline ll cal(ll a,ll b){
if(a==0) a++;
return qz[b]-qz[a-1];
}
inline ll cal(int u,int v,int x){
int lcauv =lca(u,v);
int lcauvx = lca(lcauv,x);
if(dep[lcauvx]<dep[lcauv]){
ll dis1 = dep[x]+dep[lcauv]-2*dep[lcauvx];
ll dis2 = dep[x]+dep[u]-2*dep[lcauvx];
ll dis3 = dep[x]+dep[v]-2*dep[lcauvx];
return cal(dis1,dis2)+cal(dis1, dis3)-dis1;
}
int lcaux = lca(u,x);
if(dep[lcaux]<=dep[lcauv]){
swap(u,v);
lcaux = lca(u,x);
}
ll dis1 = dep[x]-dep[lcaux];
ll dis2 = dep[x]+dep[u]-2*dep[lcaux];
ll dis3 = dep[x]+dep[v]-2*dep[lcauv];
return cal(dis1,dis2)+cal(dis1, dis3)-dis1;
}
int P[maxn];
ll dp[maxn];
void build(query *Q,ll *val,int n){
for(int i=0;i<=n;i++){
val[i] = 0;
P[i] = 0;
dp[i] = 0;
}
for(int i=0;i<S;i++){
int u = Q[i].u,v = Q[i].v,lcauv=lca(u,v);
P[u]++,P[v]++,P[lcauv]--,P[father[lcauv]]--;
}
for(int i=n;i>=1;i--){
int u = dfsv[i];
int v = father[u];
P[v]+=P[u];
dp[u]+=P[u];
dp[v]+=dp[u];
val[v]+=val[u]+dp[u];
}
for(int i=1;i<=n;i++){
int u= dfsv[i];
val[u] = val[father[u]]+dp[1]-(dp[u]<<1);
}
}
int allquery;
int bigall;
inline int lower(int st,int ed,int x){
int ret = ed;
while (st<ed) {
int mid= st+ed>>1;
if(Q[mid].x>=x){
ret = mid;
ed = mid;
}else{
st = mid+1;
}
}
return ret;
}
inline int upper(int st,int ed,int x){
int ret = ed;
while (st<ed) {
int mid= st+ed>>1;
if(Q[mid].x>x){
ret = mid;
ed = mid;
}else{
st = mid+1;
}
}
return ret;
}
int main(int argc, const char * argv[]) {
for(int i=2;i<(maxn<<1);i++){
Log2[i] = Log2[i>>1]+1;
}
for(int i=0;i<maxn;i++){
qz[i] = 1ll*(i+1)*i/2;
}
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
vv[u].push_back(v);
vv[v].push_back(u);
}
dep[1] = 0;
dfs(1,0);
ST_init();
while (m--) {
int ty,x,y,z;
scanf("%d%d%d%d",&ty,&x,&y,&z);
if(ty==1){
Q[allquery++] ={x,y,z};
if(allquery%S==0){
auto cmp = [](const query&A,const query&B){return A.x<B.x;};
sort(Q+bigall, Q+allquery, cmp);
inplace_merge(Q, Q+bigall, Q+allquery, cmp);
for(int i=0;i<(bigall=allquery)/S;i++){
build(Q+i*S, VAL[i], n);
}
}
}else{
ll res= 0;
for(int i=bigall;i<allquery;i++) if(Q[i].x<=y && Q[i].x>=x){
res+= cal(Q[i].u, Q[i].v, z);
}
int L = lower(0, bigall, x);
//int L=lower_bound(Q,Q+bigall,x,[](query A,int x){return A.x<x;})-Q;
//int R=upper_bound(Q,Q+bigall,y,[](int x,query A){return x<A.x;})-Q;
int R = upper(0, bigall, y);
if(L/S==R/S) {
for(int i=L;i<R;i++){
res+= cal(Q[i].u, Q[i].v, z);
}
}
else{
for(int i=L/S+1;i<R/S;i++) res+=VAL[i][z];
for(int i=L;i<L/S*S+S;i++) res+=cal(Q[i].u,Q[i].v,z);
for(int i=R/S*S;i<R;i++) res+=cal(Q[i].u,Q[i].v,z);
}
printf("%lld\n",res);
}
}
return 0;
}
/*
10 20
6 7
1 2
5 4
1 3
10 8
7 9
1 8
1 4
2 6
1 5 1 27280262
1 2 4 27245688
2 27234840 27290934 6
1 10 6 27227228
2 27313334 27321446 3
1 9 10 27258713
1 3 4 27249714
2 27270810 27309316 1
1 9 2 27254034
2 27292791 27302394 10
1 7 5 27319311
1 5 6 27301947
1 10 1 27318014
2 27247634 27320484 9
1 10 5 27299018
2 27240281 27286743 8
2 27296751 27319246 4
2 27309633 27314750 9
2 27257490 27301409 6
2 27235007 27294034 2
*/

浙公网安备 33010602011771号