1. 程式人生 > 其它 >魔法少女LJJ

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