Noip模拟46 2021.8.23
给了签到题,但除了签到题其他的什么也不会。。。。
T1 数数
人均$AC$,没什么好说的,就是排个序,然后双指针交换着往中间移
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 const int NN=3e5+5; 5 int n,a[NN],ans[NN],id[NN],cha[NN]; 6 inline bool cmp(int a,int b){return a>b;} 7 inline void spj(){ 8 for(int i=1;i<(1<<n);i++){ 9 int sta=i,cnt=0,tmp=0; 10 for(int j=n;j;j--){ 11 if(sta&1) id[++cnt]=j; 12 sta>>=1; 13 } 14 for(int j=1;j<=cnt;j++) 15 for(int k=j;k<=cnt;k++) 16 tmp+=abs(a[id[j]]-a[id[k]]); 17 ans[cnt]=max(ans[cnt],tmp); 18 }for(int i=1;i<=n;i++) printf("%lld\n",ans[i]); 19 } 20 namespace WSN{ 21 inline short main(){ 22 scanf("%lld",&n); 23 for(int i=1;i<=n;i++) scanf("%lld",&a[i]); 24 if(n<=5) {spj();return 0;} 25 sort(a+1,a+n+1,cmp); 26 ans[1]=0; ans[2]=a[1]-a[n]; cha[2]=ans[2]; cha[1]=0; 27 int l=1,r=n; 28 while(l<r){ 29 int num=l+n-r+1; 30 if(l==n-r+1) ans[num+1]+=ans[num]+cha[num],++l,cha[num+1]=cha[num]; 31 else{ 32 ans[num+1]+=cha[num]+a[l]-a[--r]+ans[num]; 33 cha[num+1]+=a[l]-a[r]+cha[num]; 34 } 35 }for(int i=1;i<=n;i++) printf("%lld\n",ans[i]); 36 return 0; 37 } 38 } 39 signed main(){return WSN::main();}
T2 数树
题解上说是插头$dp$,就直接跳过先改$T3$了
T3 鼠树
能和二逼平衡树相媲美的码量,思路却不知道比那个难多少
整体的思路就是只记录黑点的信息,然后询问的时候就找到管辖白点的黑点
然后进行更改和查询操作
那么关于找管辖白点的黑点,可以使用树状数组+树链剖分+二分答案轻松解决
1 inline int find_belong(int x){ 2 if(col[x]) return x; 3 while(top[x]!=1){ 4 if(zhao(dfn[x])-zhao(dfn[top[x]]-1)==0){x=fa[top[x]];continue;} 5 if(col[x]) return x; 6 int l=dfn[top[x]],r=dfn[x],ans; 7 while(l<=r){ 8 int mid=l+r>>1; 9 if(zhao(dfn[x])-zhao(mid-1)) ans=mid,l=mid+1; 10 else r=mid-1; 11 } 12 return rk[ans]; 13 } 14 int l=1,r=dfn[x],ans; 15 while(l<=r){ 16 int mid=l+r>>1; 17 if(zhao(dfn[x])-zhao(mid-1)) ans=mid,l=mid+1; 18 else r=mid-1; 19 } 20 return rk[ans]; 21 }
然后考虑如何实现各种操作。
操作1,先找管辖点,直接查他的权值
操作2,直接改那个点的值
操作3,分情况,如果这个点是白点,找到他以下黑点的信息总和,然后找到跟他一伙的白点的数量,然后找到他们的权值,算出来加上就行
如果是黑点,只找他子树里黑点的总和
操作4,直接改子树信息
操作5,改成黑点,他的归属点管辖的点个数减少,分步修改即可
操作6,维护一个差分,修改的时候带上,查询的时候加上,因为你要存下来这些退化的点的信息。
1 #include<bits/stdc++.h> 2 #define lid (id<<1) 3 #define rid (id<<1|1) 4 #define int unsigned int 5 using namespace std; 6 namespace AE86{ 7 inline int read(){ 8 int x=0,f=1; char ch=getchar(); 9 while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } 10 while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } 11 return x*f; 12 } 13 inline void write(int x,char sp){ 14 char ch[20]; int len=0; 15 if(x<0){ putchar('-'); x=~x+1; } 16 do{ ch[len++]=x%10+(1<<5)+(1<<4); x/=10; }while(x); 17 for(int i=len-1;~i;i--) putchar(ch[i]); putchar(sp); 18 } 19 } using namespace AE86; 20 21 const int NN=3e5+5; 22 int n,m,opt,K,W,col[NN]; 23 struct SNOW{int to,next;};SNOW e[NN<<1]; int head[NN],rp; 24 inline void add(int x,int y){ 25 e[++rp]=(SNOW){y,head[x]};head[x]=rp; 26 e[++rp]=(SNOW){x,head[y]};head[y]=rp; 27 } 28 namespace Tree_division{ 29 int fa[NN],son[NN],rk[NN],dfn[NN],top[NN],dep[NN],siz[NN],cnt; 30 inline void dfs1(int f,int x){ 31 siz[x]=1; dep[x]=dep[f]+1; fa[x]=f; 32 for(int i=head[x];i;i=e[i].next){ 33 int y=e[i].to; if(y==f) continue; 34 dfs1(x,y); siz[x]+=siz[y]; 35 if(siz[son[x]]<siz[y]) son[x]=y; 36 } 37 } 38 inline void dfs2(int x,int t){ 39 dfn[x]=++cnt; rk[cnt]=x; top[x]=t; 40 if(!son[x]) return; dfs2(son[x],t); 41 for(int i=head[x];i;i=e[i].next){ 42 int y=e[i].to; 43 if(y!=fa[x]&&y!=son[x]) dfs2(y,y); 44 } 45 } 46 }using namespace Tree_division; 47 48 namespace Tree_array{ 49 int tr[NN]; 50 inline int lowbit(int x){return x&(-x);} 51 inline void charu(int x,int v){for(;x<=n;x+=lowbit(x)) tr[x]+=v;} 52 inline int zhao(int x){int ans=0;for(;x;x-=lowbit(x)) ans+=tr[x];return ans;} 53 }using namespace Tree_array; 54 55 namespace SNOWtree{ 56 int ll[NN<<2],rr[NN<<2]; 57 int num[NN<<2],sum[NN<<2],laz[NN<<2],mul[NN<<2]; 58 int cha[NN<<2],lac[NN<<2]; 59 inline void pushdown(int id){ 60 if(laz[id]){ 61 mul[lid]+=num[lid]*laz[id]; mul[rid]+=num[rid]*laz[id]; 62 sum[lid]+=laz[id]; sum[rid]+=laz[id]; 63 laz[lid]+=laz[id]; laz[rid]+=laz[id]; 64 } 65 if(lac[id]){ 66 int mid=ll[id]+rr[id]>>1; 67 cha[lid]+=lac[id]*(mid-ll[id]+1); cha[rid]+=lac[id]*(rr[id]-mid); 68 lac[lid]+=lac[id]; lac[rid]+=lac[id]; 69 } 70 laz[id]=lac[id]=0; 71 } 72 inline void pushup(int id){ 73 if(ll[id]==rr[id]) return; 74 num[id]=num[lid]+num[rid]; sum[id]=sum[lid]+sum[rid]; 75 mul[id]=mul[lid]+mul[rid]; cha[id]=cha[lid]+cha[rid]; 76 } 77 inline void build(int id,int l,int r){ 78 ll[id]=l; rr[id]=r; 79 if(l==r) return; int mid=l+r>>1; 80 build(lid,l,mid); build(rid,mid+1,r); 81 } 82 inline void insert(int id,int pos,int shu,int val){//插入黑点 83 if(ll[id]==rr[id]){ 84 num[id]=shu; sum[id]=val; 85 mul[id]=shu*val; 86 return; 87 }pushdown(id);int mid=ll[id]+rr[id]>>1; 88 if(pos<=mid) insert(lid,pos,shu,val); 89 else insert(rid,pos,shu,val); 90 pushup(id); 91 } 92 inline void clear(int id,int pos){//删除黑点 93 if(ll[id]==rr[id]){ 94 num[id]=sum[id]=mul[id]=0; 95 return; 96 }pushdown(id);int mid=ll[id]+rr[id]>>1; 97 if(pos<=mid) clear(lid,pos); 98 else clear(rid,pos); 99 pushup(id); 100 } 101 inline void change(int id,int l,int r,int val){//加w 102 if(l<=ll[id]&&rr[id]<=r){ 103 sum[id]+=val; laz[id]+=val; 104 mul[id]+=val*num[id]; 105 return; 106 }pushdown(id);int mid=ll[id]+rr[id]>>1; 107 if(l<=mid) change(lid,l,r,val); 108 if(r>mid) change(rid,l,r,val); 109 pushup(id); 110 } 111 inline void update(int id,int l,int r,int val){//加差分 112 if(l<=ll[id]&&rr[id]<=r){ 113 cha[id]+=val*(rr[id]-ll[id]+1); 114 lac[id]+=val; 115 return; 116 }pushdown(id); int mid=ll[id]+rr[id]>>1; 117 if(l<=mid) update(lid,l,r,val); 118 if(r>mid) update(rid,l,r,val); 119 pushup(id); 120 } 121 inline int look(int id,int l,int r){//区间求差分 122 if(l<=ll[id]&&rr[id]<=r) return cha[id]; 123 pushdown(id); int mid=ll[id]+rr[id]>>1,ans=0; 124 if(l<=mid) ans+=look(lid,l,r); 125 if(r>mid) ans+=look(rid,l,r); 126 return ans; 127 } 128 inline int query(int id,int l,int r){//区间求w×c 129 if(l<=ll[id]&&rr[id]<=r) return mul[id]; 130 pushdown(id);int mid=ll[id]+rr[id]>>1,ans=0; 131 if(l<=mid) ans+=query(lid,l,r); 132 if(r>mid) ans+=query(rid,l,r); 133 return ans; 134 } 135 inline int search(int id,int l,int r){//区间求c 136 if(l<=ll[id]&&rr[id]<=r) return num[id]; 137 pushdown(id);int mid=ll[id]+rr[id]>>1,ans=0; 138 if(l<=mid) ans+=search(lid,l,r); 139 if(r>mid) ans+=search(rid,l,r); 140 return ans; 141 } 142 inline int found(int id,int pos){//单点求w 143 if(ll[id]==rr[id]) return sum[id]; 144 pushdown(id);int mid=ll[id]+rr[id]>>1; 145 if(pos<=mid) return found(lid,pos); 146 else return found(rid,pos); 147 } 148 }using namespace SNOWtree; 149 150 inline int find_belong(int x){ 151 if(col[x]) return x; 152 while(top[x]!=1){ 153 if(zhao(dfn[x])-zhao(dfn[top[x]]-1)==0){x=fa[top[x]];continue;} 154 if(col[x]) return x; 155 int l=dfn[top[x]],r=dfn[x],ans; 156 while(l<=r){ 157 int mid=l+r>>1; 158 if(zhao(dfn[x])-zhao(mid-1)) ans=mid,l=mid+1; 159 else r=mid-1; 160 } 161 return rk[ans]; 162 } 163 int l=1,r=dfn[x],ans; 164 while(l<=r){ 165 int mid=l+r>>1; 166 if(zhao(dfn[x])-zhao(mid-1)) ans=mid,l=mid+1; 167 else r=mid-1; 168 } 169 return rk[ans]; 170 } 171 172 namespace WSN{ 173 inline short main(){ 174 // freopen("pastel5.in","r",stdin); 175 // freopen("1.in","r",stdin); 176 // freopen("1.out","w",stdout); 177 n=read();m=read(); 178 for(int i=2;i<=n;i++) add(read(),i); 179 dfs1(0,1); dfs2(1,1); build(1,1,n); 180 col[1]=1; charu(1,1); insert(1,1,siz[1],0); 181 while(m--){ 182 opt=read();K=read(); if(opt==2||opt==4) W=read(); 183 if(opt==1){ 184 int ruler=find_belong(K); 185 write(found(1,dfn[ruler])+look(1,dfn[K],dfn[K]),'\n'); 186 } 187 if(opt==2) change(1,dfn[K],dfn[K],W); 188 if(opt==3){ 189 int ruler=find_belong(K),res=0; 190 int cheng=query(1,dfn[K],dfn[K]+siz[K]-1); 191 int geshu=siz[K]-search(1,dfn[K],dfn[K]+siz[K]-1); 192 int Sum=found(1,dfn[ruler]); 193 if(!col[K]) res+=geshu*Sum; 194 res+=cheng; write(res+look(1,dfn[K],dfn[K]+siz[K]-1),'\n'); 195 } 196 if(opt==4) change(1,dfn[K],dfn[K]+siz[K]-1,W); 197 if(opt==5){ 198 int ruler=find_belong(K); 199 int NUM=siz[K]-search(1,dfn[K],dfn[K]+siz[K]-1); 200 int VAL=found(1,dfn[ruler]); 201 col[K]=1; charu(dfn[K],1); insert(1,dfn[K],NUM,VAL); 202 insert(1,dfn[ruler],search(1,dfn[ruler],dfn[ruler])-NUM,VAL); 203 } 204 if(opt==6){ 205 int Siz=search(1,dfn[K],dfn[K]); 206 col[K]=0; charu(dfn[K],-1); 207 int ruler=find_belong(K); 208 int Cha=found(1,dfn[K])-found(1,dfn[ruler]); 209 insert(1,dfn[ruler],search(1,dfn[ruler],dfn[ruler])+Siz,found(1,dfn[ruler])); 210 update(1,dfn[K],dfn[K]+siz[K]-1,Cha); 211 clear(1,dfn[K]); 212 change(1,dfn[K],dfn[K]+siz[K]-1,-Cha); 213 } 214 } 215 return 0; 216 } 217 } 218 signed main(){return WSN::main();}
T4 ckw的树
沽了