bzoj 3600 没有人的算术
50分的做法:
50分的程序:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define lc (x<<1) 4 #define rc (x<<1|1) 5 #define mid (l+r>>1) 6 int const N=100000+10; 7 int const M=500000+10; 8 map<pair<int,int>,int > mat; 9 int n,m,sum,a[N],b[N],id[N],x[N],y[N]; 10 int s[5001][5001],t[N<<2]; 11 int check(int t1,int t2){ 12 if(t2==0 && t1) return 1; 13 if(t1==0 && t2) return -1; 14 int t=s[x[t1]][x[t2]]; 15 if(t) return t; 16 return s[y[t1]][y[t2]]; 17 } 18 void pushup(int x){ 19 int lch=id[t[lc]]; 20 int rch=id[t[rc]]; 21 if(check(lch,rch)>=0) 22 t[x]=t[lc]; 23 else t[x]=t[rc]; 24 } 25 void build(int x,int l,int r){ 26 if(l==r) { 27 t[x]=l; 28 return; 29 } 30 build(lc,l,mid); 31 build(rc,mid+1,r); 32 pushup(x); 33 } 34 void update(int x,int l,int r,int p){ 35 if(l==r) return; 36 if(p<=mid) update(lc,l,mid,p); 37 else update(rc,mid+1,r,p); 38 pushup(x); 39 } 40 int query(int x,int l,int r,int ll,int rr){ 41 if(ll<=l && r<=rr) return t[x]; 42 int v1=0,v2=0; 43 if(ll<=mid) v1=query(lc,l,mid,ll,rr); 44 if(rr>mid) v2=query(rc,mid+1,r,ll,rr); 45 int lch=id[v1]; 46 int rch=id[v2]; 47 if(check(lch,rch)>=0) return v1; 48 else return v2; 49 } 50 int main(){ 51 scanf("%d%d",&n,&m); 52 sum=1; 53 s[1][0]=1; 54 s[0][1]=-1; 55 x[1]=y[1]=0; 56 mat[make_pair(0,0)]=1; 57 for(int i=1;i<=n;i++) 58 a[i]=b[i]=0,id[i]=1; 59 build(1,1,n); 60 while (m--){ 61 char st[2]; 62 int l,r,k; 63 scanf("%s",st); 64 scanf("%d%d",&l,&r); 65 if(st[0]=='C'){ 66 scanf("%d",&k); 67 int d=id[l]; 68 int t=id[r]; 69 a[k]=d; 70 b[k]=t; 71 if(mat[make_pair(d,t)]==0) { 72 mat[make_pair(d,t)]=++sum; 73 x[sum]=d; y[sum]=t; 74 for(int i=0;i<sum;i++){ 75 s[sum][i]=check(sum,i); 76 s[i][sum]=check(i,sum); 77 } 78 } 79 id[k]=mat[make_pair(d,t)]; 80 update(1,1,n,k); 81 }else { 82 printf("%d\n",query(1,1,n,l,r)); 83 } 84 } 85 return 0; 86 } 87 /* 88 5 10 89 C 1 1 1 90 C 2 1 2 91 Q 1 2 92 C 4 4 4 93 C 5 5 5 94 Q 4 5 95 Q 3 3 96 C 4 2 3 97 C 4 4 4 98 Q 3 4 99 */
70分的思想: 可以让平衡树来维护名次,这样就可以在$logn$的时间内比较两个数的大小 。
总的时间复杂度就是$O(m*logn*logn)$了,由于n和m比较大,只能拿70分。
100分的思想:
这个做法非常好的,值得借鉴。
我的满分程序:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 #define mid (l+r>>1) 5 #define lc (x<<1) 6 #define rc (x<<1|1) 7 int const N=100000+10; 8 int const M=1000000+10; 9 LL const inf=(1LL<<62)-1; 10 int n,m,rt,sum,id[M]; 11 LL v[M]; 12 struct node{ 13 int l,r,w; 14 friend bool operator < (node x,node y){ 15 return v[x.l]<v[y.l] || v[x.l]==v[y.l] && v[x.r]<v[y.r]; 16 } 17 friend bool operator ==(node x,node y){ 18 return v[x.l]==v[y.l] && v[x.r]==v[y.r]; 19 } 20 }a[M],st[M<<2],t[M]; 21 22 struct sctree{ 23 int ls[M],rs[M],sz[M],R,top,s[M]; 24 int build(int l,int r,LL ll,LL rr){ 25 if(l>r) return 0; 26 int root=s[mid]; 27 v[root]=(ll+rr)/2; 28 ls[root]=build(l,mid-1,ll,(ll+rr)/2-1); 29 rs[root]=build(mid+1,r,(ll+rr)/2+1,rr); 30 sz[root]=sz[ls[root]]+sz[rs[root]]+1; 31 return root; 32 } 33 void dfs(int x){ 34 if(!x) return; 35 dfs(ls[x]); 36 s[++top]=x; 37 dfs(rs[x]); 38 } 39 void rebuild(int &x,LL l,LL r){ 40 top=0; 41 dfs(x); 42 x=build(1,top,l,r); 43 } 44 int insert(int &x,LL l,LL r,node p){ 45 if(!x){ 46 x=++sum;v[x]=mid; sz[x]=1; t[x]=p; return x; 47 } 48 if(t[x]==p) return x; 49 int ret; 50 if(p<t[x]) ret=insert(ls[x],l,mid,p); 51 else ret=insert(rs[x],mid+1,r,p); 52 sz[x]=sz[ls[x]]+sz[rs[x]]+1; 53 if(max(sz[ls[x]],sz[rs[x]])>0.75* sz[x]) 54 rebuild(x,l,r); 55 return ret; 56 } 57 void db(int x){ 58 if(!x) return; 59 db(ls[x]); 60 cout<<x<<" "<<v[x]<<" "<<t[x].l<<" "<<t[x].r<<endl; 61 db(rs[x]); 62 } 63 }sc; 64 void modify(int x,int l,int r,int p,node v){ 65 if(l==r){ 66 st[x]=v; st[x].w=l; return; 67 } 68 if(p<=mid) modify(lc,l,mid,p,v); 69 else modify(rc,mid+1,r,p,v); 70 node t1=st[lc]; 71 node t2=st[rc]; 72 if(t1<t2) st[x]=t2; 73 else st[x]=t1; 74 } 75 node query(int x,int l,int r,int ll,int rr){ 76 if(l==ll && r==rr) return st[x]; 77 if(rr<=mid) return query(lc,l,mid,ll,rr); 78 else if(ll>mid) return query(rc,mid+1,r,ll,rr); 79 else { 80 node t1=query(lc,l,mid,ll,mid); 81 node t2=query(rc,mid+1,r,mid+1,rr); 82 if(t1<t2) return t2; 83 else return t1; 84 } 85 } 86 int main(){ 87 scanf("%d%d",&n,&m); 88 sc.insert(rt,1,inf,node{0,0,0}); 89 for(int i=1;i<=n;i++) 90 id[i]=1; 91 for(int i=1;i<=n;i++) 92 modify(1,1,n,i,node{0,0,i}); 93 while (m--){ 94 char cmd[3]; 95 int l,r,k; 96 scanf("%s%d%d",cmd,&l,&r); 97 if(cmd[0]=='C'){ 98 scanf("%d",&k); 99 a[k].l=id[l]; 100 a[k].r=id[r]; 101 id[k]=sc.insert(rt,1,inf,node{id[l],id[r],0}); 102 modify(1,1,n,k,a[k]); 103 }else printf("%d\n",query(1,1,n,l,r).w); 104 } 105 return 0; 106 } 107 /* 108 5 10 109 C 1 1 1 110 C 2 1 2 111 Q 1 2 112 C 4 4 4 113 C 5 5 5 114 Q 4 5 115 Q 3 3 116 C 4 2 3 117 C 4 4 4 118 Q 3 4 119 */