魔法少女LJJ
大悲 就这道 破题 好题,我NM调了一个多星期。
简而言之 七种操作
并查集维护块和块的大小
权值线段树维护块点数和点权
lazy维护是否需要修改
比乘积则通过log将积转化为和,int就能过
上代码 (本人码风还不错哦 QAQ)
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <utility> 5 #include <iomanip> 6 #include <cstdio> 7 #include <vector> 8 #include <queue> 9 #include <stack> 10 #include <cmath> 11 #include <map> 12 13 using namespace std; 14 15 #define dd double 16 #define ll long long 17 #define ull unsigned long long 18 #define rint register int 19 #define lson(x) tree[x].ls 20 #define rson(x) tree[x].rs 21 22 const int INF=0x3f,INFF=0x3f3f3f3f,INFFF=0x7fffffff; 23 const int maxn=4e5+10,maxx=1e9; 24 25 /* 26 c==1 x 新建一个节点权值为x的编号为tot+1的节点 27 c==2 a,b 在a,b之间连一条边 28 c==3 a,x 把联通块a中原本权值 小于x 的节点全部变为x 29 c==4 a,x 把联通块a中原本权值 大于x 的节点全部变为x 30 31 c==5 a,k 询问 联通块a中第k小的权值 是多少 32 c==6 a,b 询问 联通块a所有节点的权值之积 与 联通块b所有节点的权值之积 的大小, 33 a>b 输出1 ; a<b 输出0 ; 34 c==7 a 询问 联通块a大小 35 36 */ 37 38 int n,m,q,cnt; 39 int rt[maxn],d[maxn],ans[maxn]; 40 41 inline int read(){ 42 int x=0,w=0;char ch=getchar(); 43 while(ch<'0' || ch>'9'){if(ch=='-')w=1;ch=getchar();} 44 while(ch>='0' && ch<='9'){x=(x<<3)+(x<<1)+(ch^'0');ch=getchar();} 45 if(w)return -x; 46 return x; 47 } 48 49 struct BCJ{ 50 int fa[maxn<<1],sz[maxn<<1]; 51 void csh(int x){ fa[x]=x,sz[x]=1; return;} 52 int find(int x){ 53 return fa[x]==x ? x : fa[x]=find(fa[x]); 54 } 55 }B; 56 57 struct XDS{ 58 struct Node{ 59 int ls,rs,sum; 60 dd val; 61 }tree[maxn*20]; 62 int tot; 63 bool lazy[maxn*20]; 64 void pushup(int rt){ 65 tree[rt].sum=tree[lson(rt)].sum+tree[rson(rt)].sum, 66 tree[rt].val=tree[lson(rt)].val+tree[rson(rt)].val; 67 return; 68 } 69 void pushdown(int rt){ 70 if(lazy[rt]){ 71 lazy[lson(rt)]=1, lazy[rson(rt)]=1, 72 tree[lson(rt)].sum=0,tree[lson(rt)].val=0, 73 tree[rson(rt)].sum=0,tree[rson(rt)].val=0, 74 lazy[rt]=0; 75 } 76 return; 77 } 78 void Updata(int& rt,int l,int r,int val){ 79 if(!rt)rt=++tot; 80 if(l==r){ 81 tree[rt].sum++,tree[rt].val+=log(l); 82 return ; 83 } 84 else{ 85 int mid=((l+r)>>1); 86 if(val<=mid) 87 Updata(lson(rt),l,mid,val); 88 else Updata(rson(rt),mid+1,r,val); 89 pushup(rt); 90 } 91 return ; 92 } 93 void Updata_min_to_x(int& rt,int l,int r,int val,int x){ 94 if(!rt)rt=++tot; 95 if(l==r){ 96 tree[rt].sum+=x, 97 tree[rt].val+=log(l)*x; 98 return; 99 } 100 else{ 101 int mid=((l+r)>>1); 102 pushdown(rt); 103 if(val<=mid) 104 Updata_min_to_x(lson(rt),l,mid,val,x); 105 else{ 106 x+=tree[lson(rt)].sum, 107 tree[lson(rt)].val=0, 108 tree[lson(rt)].sum=0, 109 lazy[lson(rt)]=1; 110 Updata_min_to_x(rson(rt),mid+1,r,val,x); 111 } 112 pushup(rt); 113 return; 114 } 115 } 116 void Updata_max_to_x(int& rt,int l,int r,int val,int x){ 117 if(!rt)rt=++tot; 118 if(l==r){ 119 tree[rt].sum+=x, 120 tree[rt].val+=log(l)*x; 121 return; 122 } 123 else{ 124 int mid=((l+r)>>1); 125 pushdown(rt); 126 if(val<=mid){ 127 x+=tree[rson(rt)].sum, 128 tree[rson(rt)].val=0, 129 tree[rson(rt)].sum=0, 130 lazy[rson(rt)]=1; 131 Updata_max_to_x(lson(rt),l,mid,val,x); 132 } 133 else 134 Updata_max_to_x(rson(rt),mid+1,r,val,x); 135 pushup(rt); 136 return; 137 } 138 } 139 void merge(int& a,int b){ 140 if(!a || !b){ a=a+b; return;} 141 else{ 142 pushdown(a), 143 pushdown(b); 144 tree[a].val+=tree[b].val, 145 tree[a].sum+=tree[b].sum; 146 merge(lson(a),lson(b)), 147 merge(rson(a),rson(b)); 148 return; 149 } 150 } 151 int Query(int rt,int l,int r,int k){ 152 if(l==r)return l; 153 else{ 154 pushdown(rt); 155 int mid=((l+r)>>1); 156 if(tree[lson(rt)].sum>=k) 157 return Query(lson(rt),l,mid,k); 158 else 159 return Query(rson(rt),mid+1,r,k-tree[lson(rt)].sum); 160 } 161 } 162 }F; 163 164 void Solve(){ 165 q=read(); 166 while(q--){ 167 int x=0,y=0,c=read(); 168 if(c==1){ //新建一个节点权值为x的编号为tot+1的节点 169 x=read(), B.csh(++n), F.Updata(rt[n],1,maxx,x); 170 } 171 else if(c==2){ //在a,b之间连一条边 172 x=B.find(read()), y=B.find(read()); 173 if(x!=y){ 174 if(B.sz[x] > B.sz[y]) 175 B.sz[x]+=B.sz[y], B.fa[y]=x, 176 F.merge(rt[x],rt[y]); 177 else 178 B.sz[y]+=B.sz[x], B.fa[x]=y, 179 F.merge(rt[y],rt[x]); 180 } 181 } 182 else if(c==3){ //把联通块a中原本权值 小于x 的节点全部变为x 183 x=B.find(read()), y=read(); 184 F.Updata_min_to_x(rt[x],1,maxx,y,0); 185 } 186 else if(c==4){ //把联通块a中原本权值 大于x 的节点全部变为x 187 x=B.find(read()), y=read(); 188 F.Updata_max_to_x(rt[x],1,maxx,y,0); 189 } 190 else if(c==5){ //询问 联通块xa中第k小的权值 是多少 191 x=B.find(read()), y=read() ; 192 printf("%d\n",F.Query(rt[x],1,maxx,y)); 193 } 194 else if(c==6){ /*询问 联通块a所有节点的权值之积 与 195 联通块b所有节点的权值之积 的大小, 196 a>b 输出1 ; a<=b 输出0 ;*/ 197 x=B.find(read()), y=B.find(read()); 198 if(F.tree[rt[x]].val > F.tree[rt[y]].val) 199 printf("1\n"); 200 else printf("0\n"); 201 } 202 else if(c==7){ //c==7 a 询问 联通块a大小 203 x=B.find(read()); 204 printf("%d\n",B.sz[x]); 205 } 206 207 } 208 return; 209 } 210 int main(){ 211 //freopen("xds.in","r",stdin); 212 Solve(); 213 return 0; 214 } 215 /* 216 c==1 x 新建一个节点权值为x的编号为tot+1的节点 217 c==2 a,b 在a,b之间连一条边 218 219 c==3 a,x 把联通块a中原本权值 小于x 的节点全部变为x 220 c==4 a,x 把联通块a中原本权值 大于x 的节点全部变为x 221 222 c==5 a,k 询问 联通块a中第k小的权值 是多少 223 c==6 a,b 询问 联通块a所有节点的权值之积 与 联通块b所有节点的权值之积 的大小, 224 a>b 输出1 ; a<b 输出0 ; 225 c==7 a 询问 联通块a大小 226 227 */
再副对拍用rand函数一张
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxx=1e4; 4 long long random(int n){ 5 return (1LL<<15)*rand()+rand(); 6 } 7 //rand()的返回值为[0,RAMD_MAX)的整数; 8 //注意 linux中RAND_MAX值为2147483647; 9 int n=0; 10 int main() 11 { 12 std::ios::sync_with_stdio(false); 13 srand((unsigned)time(NULL)); 14 int m=rand()%40000; 15 while(m<100)m=rand()%40000; 16 cout<<m<<endl; 17 int n=rand()%m; 18 while(n<50)n=rand()%m; 19 int nn=n; 20 while(nn--){ 21 int Node=rand()%maxx; 22 while(!Node)Node=rand()%maxx; 23 cout<<"1 "<<Node<<endl; 24 } 25 m-=n; 26 for(int i=1;i<=m;i++){ 27 int k=rand()%7; 28 k==0 ? k=1 : k; 29 cout<<k<<" "; 30 if(k==1){ 31 int Node=rand()%maxx; 32 n++; 33 while(!Node)Node=rand()%maxx; 34 cout<<Node<<endl; 35 } 36 else if(k==2){ 37 int Nodea=rand()%maxx,Nodeb=rand()%maxx; 38 while(!Nodea || !Nodeb || Nodea==Nodeb) 39 Nodea=rand()%maxx,Nodeb=rand()%maxx; 40 cout<<Nodea<<" "<<Nodeb<<endl; 41 } 42 else if(k==3){ 43 int x=rand()%n,Node=rand()%maxx; 44 while(!x)x=rand()%n; 45 while(!Node)Node=rand()%maxx; 46 cout<<n<<" "<<Node<<endl; 47 } 48 else if(k==4){ 49 int x=rand()%n,Node=rand()%maxx; 50 while(!x)x=rand()%n; 51 while(!Node)Node=rand()%maxx; 52 cout<<n<<" "<<Node<<endl; 53 } 54 else if(k==5){ 55 int x=rand()%n,Node=rand()%n; 56 while(!x)x=rand()%n; 57 while(!Node)Node=rand()%n; 58 cout<<x<<" "<<Node<<endl; 59 } 60 else if(k==6){ 61 int x=rand()%n,y=rand()%n; 62 while(!x || !y || x==y)x=rand()%n,y=rand()%n; 63 cout<<x<<" "<<y<<endl; 64 } 65 else{ 66 int x=rand()%n; 67 while(!x)x=rand()%n; 68 cout<<x<<endl; 69 } 70 } 71 return 0; 72 }