魔法少女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 }

 

posted @ 2022-04-02 20:28  Eakang  阅读(35)  评论(0编辑  收藏  举报