数据结构讲题选做

//下面内容请选择性阅读

一些胡乱的感受:

抽 象 主 义 解 题

充分让我认识到了我的码力有多么弱

我真是对力量一无所知

*你妈的,随便伤害无辜少年*

维护维护维护维护维护维护

猫不仅喜欢上树,还喜欢上数据结构

sto immortalco orz

— —好了,还有什么人要提问

— —我要!

— —什么?

— —我写乱搞淦猫式上树树上问题,好吗

— —好!

*激烈的调试大赛*

//正文开始了

CodePlus 2018 3 月赛 寻找车位

线段树神仙题

什么,我的题解?去看i207M的吧

  1 // luogu-judger-enable-o2
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int N=4e6+60,inf=1e9;
  7 int n,m,q,t1,t2,t3,t4,typ,len[N*4];
  8 struct a
  9 {
 10     int arr[N*4];
 11     int* operator[] (int x)
 12     {
 13         return arr+x*m;
 14     }
 15 }mapp,upp,low,mat;
 16 struct Mono_queue
 17 {
 18     int f,b,que[N];
 19     int* arr;
 20     int Size(){return b-f+1;}
 21     int Front(){return arr[que[f]];}
 22     void Init(int* ar){f=0,b=-1,arr=ar;}
 23     void Pop(int x){while(f<=b&&que[f]<=x) f++;}
 24     void Push(int x){while(f<=b&&arr[x]<=arr[que[b]]) b--;que[++b]=x;}
 25 };
 26 int Calc(int x,int y,int l,int r)
 27 {
 28     int ret=0;
 29     static Mono_queue q1,q2;
 30     q1.Init(upp[x]),q2.Init(low[y]);
 31     for(int b=l,f=l;b<=r;b++)
 32     {
 33         q1.Push(b),q2.Push(b);
 34         while(q1.Size()&&q2.Size()&&f<=b&&q1.Front()+q2.Front()<b-f+1)
 35             q1.Pop(f),q2.Pop(f),f++;
 36         ret=max(ret,b-f+1);
 37     }
 38     int *a1=upp[x],*a2=upp[y];
 39     for(int i=l;i<=r;i++) a1[i]=(a2[i]==len[y])?a1[i]+len[y]:a2[i];
 40     len[x]+=len[y];
 41     return ret;
 42 }
 43 void Pushup(int p,int x,int y)
 44 {
 45     static Mono_queue q1,q2;
 46     q1.Init(upp[x]),q2.Init(low[y]);
 47     int *a1=mat[p],*a2=mat[x],*a3=mat[y];
 48     for(int b=1,f=1;b<=m;b++)
 49     {
 50         q1.Push(b),q2.Push(b);
 51         while(q1.Size()&&q2.Size()&&f<=b&&q1.Front()+q2.Front()<b-f+1)
 52             q1.Pop(f),q2.Pop(f),f++;
 53         a1[b]=max(b-f+1,max(a2[b],a3[b]));
 54     }
 55     a1=upp[p],a2=upp[x],a3=upp[y];
 56     for(int i=1;i<=m;i++) a1[i]=(a3[i]==len[y])?a2[i]+len[y]:a3[i];
 57     a1=low[p],a2=low[x],a3=low[y];
 58     for(int i=1;i<=m;i++) a1[i]=(a2[i]==len[x])?a3[i]+len[x]:a2[i];
 59     len[p]=len[x]+len[y];
 60 }
 61 void Create(int nde,int l,int r)
 62 {
 63     if(l==r)
 64     {
 65         len[nde]=1;
 66         for(int i=1;i<=m;i++)
 67             upp[nde][i]=low[nde][i]=mapp[l][i];
 68     }
 69     else
 70     {
 71         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
 72         Create(ls,l,mid),Create(rs,mid+1,r),Pushup(nde,ls,rs);
 73     }
 74 }
 75 void Change(int nde,int l,int r,int pos,int tsk)
 76 {
 77     if(l==r)
 78         mapp[l][tsk]^=1,upp[nde][tsk]=low[nde][tsk]=mapp[l][tsk];
 79     else
 80     {
 81         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
 82         if(pos<=mid) Change(ls,l,mid,pos,tsk);
 83         else Change(rs,mid+1,r,pos,tsk); Pushup(nde,ls,rs);
 84     }
 85 }
 86 int Query(int nde,int l,int r,int nl,int nr,int ml,int mr)
 87 {
 88     if(l>=nl&&r<=nr)
 89     {
 90         int ret=Calc(0,nde,ml,mr);
 91         int *arr=mat[nde];
 92         for(int i=ml;i<=mr;i++)
 93             ret=max(ret,min(arr[i],i-ml+1));
 94         return ret;
 95     }
 96     else
 97     {
 98         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1,ret=0;
 99         if(mid>=nl) ret=max(ret,Query(ls,l,mid,nl,nr,ml,mr));
100         if(mid<nr) ret=max(ret,Query(rs,mid+1,r,nl,nr,ml,mr));
101         return ret;
102     }
103 }
104 int main()
105 {
106     scanf("%d%d%d",&n,&m,&q);
107     for(int i=1;i<=n;i++)
108         for(int j=1;j<=m;j++)
109             scanf("%d",&mapp[i][j]);
110     Create(1,1,n);
111     while(q--)
112     {
113         scanf("%d%d%d",&typ,&t1,&t2);
114         if(!typ) Change(1,1,n,t1,t2);
115         else
116         {
117             scanf("%d%d",&t3,&t4);
118             for(int i=1;i<=m;i++) upp[0][i]=0; len[0]=0;
119             printf("%d
",Query(1,1,n,t1,t3,t2,t4));
120         }
121     }
122     return 0;
123 }
View Code

清华集训 2016 数据交互

两条链有交当且仅当有一条链的LCA在另一条链上,动态DP

被卡常了,卡了一会,没卡过去,懒得卡了

什么,我的题解?去看这位神仙的吧

  1 #include<set>
  2 #include<cstdio>
  3 #include<cctype>
  4 #include<cstring>
  5 #include<algorithm>
  6 using namespace std;
  7 const int N=100005;
  8 int n,m,t1,t2,rd,cnt,tot;
  9 long long laz[4*N],val[4*N]; char str[10];
 10 int p[N],noww[2*N],goal[2*N],u[N],v[N],w[N],endp[N];
 11 int siz[N],far[N],dep[N],imp[N],top[N],dfn[N],ori[N];
 12 multiset<long long> st,ss[N]; 
 13 struct a
 14 {
 15     long long ll,rr,mx,sum;
 16 }seg[4*N];
 17 a operator + (a x,a y)
 18 {
 19     a ret;
 20     ret.ll=max(x.ll,x.sum+y.ll);
 21     ret.rr=max(y.rr,y.sum+x.rr);
 22     ret.mx=max(max(x.mx,y.mx),x.rr+y.ll);
 23     ret.sum=x.sum+y.sum; return ret;
 24 }
 25 void Read(int &x)
 26 {
 27     x=0; char ch=getchar();
 28     while(!isdigit(ch))
 29         ch=getchar();
 30     while(isdigit(ch))
 31         x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
 32 } 
 33 void Link(int f,int t)
 34 {
 35     noww[++cnt]=p[f];
 36     goal[cnt]=t,p[f]=cnt;
 37     noww[++cnt]=p[t];
 38     goal[cnt]=f,p[t]=cnt;
 39 }
 40 void DFS(int nde,int fth,int dth)
 41 {
 42     int tmp=0;
 43     siz[nde]=1,far[nde]=fth,dep[nde]=dth;
 44     for(int i=p[nde];i;i=noww[i])
 45         if(goal[i]!=fth)
 46         {
 47             DFS(goal[i],nde,dth+1);
 48             siz[nde]+=siz[goal[i]];
 49             if(siz[goal[i]]>tmp)
 50                 tmp=siz[goal[i]],imp[nde]=goal[i];
 51         }
 52 }
 53 void Mark(int nde,int tpp)
 54 {
 55     top[nde]=tpp,dfn[nde]=++tot;
 56     endp[nde]=dfn[nde],ori[tot]=nde;
 57     if(imp[nde])
 58     {
 59         Mark(imp[nde],tpp);
 60         endp[nde]=endp[imp[nde]];
 61         for(int i=p[nde];i;i=noww[i])
 62             if(goal[i]!=far[nde]&&goal[i]!=imp[nde])
 63                 ss[nde].insert(0),Mark(goal[i],goal[i]);
 64     }
 65     else st.insert(0);
 66 }
 67 int LCA(int x,int y)
 68 {
 69     while(top[x]!=top[y])
 70     {
 71         if(dep[top[x]]<dep[top[y]])
 72             swap(x,y); x=far[top[x]];
 73     }
 74     return dep[x]<dep[y]?x:y;
 75 }
 76 void Release(int nde)
 77 {
 78     if(laz[nde])
 79     {
 80         int ls=2*nde,rs=2*nde+1,lz=laz[nde];
 81         laz[ls]+=lz,seg[ls].rr+=lz,seg[ls].mx+=lz;
 82         laz[rs]+=lz,seg[rs].rr+=lz,seg[rs].mx+=lz;
 83         laz[nde]=0;
 84     }
 85 }
 86 a Query(int nde,int l,int r,int ll,int rr)
 87 {
 88     if(l>=ll&&r<=rr)
 89         return seg[nde];
 90     else
 91     {
 92         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; Release(nde);
 93         if(mid>=rr) return Query(ls,l,mid,ll,rr);
 94         else if(mid<ll) return Query(rs,mid+1,r,ll,rr);
 95         else return Query(ls,l,mid,ll,rr)+Query(rs,mid+1,r,ll,rr);
 96     }
 97 }
 98 void Ex(int nde,int l,int r,int pos,long long tsk)
 99 {
100     if(l==r)
101     {
102         int orn=ori[l]; long long ret=0;
103         val[nde]+=tsk,seg[nde].sum=val[nde];
104         multiset<long long> ::iterator it=ss[orn].end();    
105         if(ss[orn].size()>=1) ret+=*(--it);
106         seg[nde].ll=val[nde]+ret,seg[nde].rr=val[nde]+ret+laz[nde];
107         if(ss[orn].size()>=2) ret+=*(--it);
108         seg[nde].mx=val[nde]+ret+laz[nde];
109     }
110     else
111     {
112         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; Release(nde);
113         if(pos<=mid) Ex(ls,l,mid,pos,tsk);
114         else Ex(rs,mid+1,r,pos,tsk); seg[nde]=seg[ls]+seg[rs];
115     }
116 }
117 void Exc(int nde,int l,int r,int ll,int rr,int tsk)
118 {
119     if(l>rr||r<ll)
120         return;
121     else if(l>=ll&&r<=rr)
122         seg[nde].rr+=tsk,seg[nde].mx+=tsk,laz[nde]+=tsk;
123     else
124     {
125         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; Release(nde);
126         Exc(ls,l,mid,ll,rr,tsk),Exc(rs,mid+1,r,ll,rr,tsk);
127         seg[nde]=seg[ls]+seg[rs];
128     }
129 }
130 void Modify(int nde,long long val,int lca,int tsk)
131 {
132     while(nde)
133     {
134         int l=lca?max(dfn[top[nde]],dfn[lca]+1):n+1;
135         int r=dfn[nde],nxt=far[top[nde]];
136         if(nxt)
137         {
138             a x=Query(1,1,n,dfn[top[nxt]],endp[nxt]);
139             st.erase(st.lower_bound(x.mx));
140             ss[nxt].erase(ss[nxt].lower_bound(val)),val=x.ll;
141         }
142         if(l<=r)
143         {
144             st.erase(st.lower_bound(Query(1,1,n,dfn[top[nde]],endp[nde]).mx));
145             Exc(1,1,n,l,r,tsk),st.insert(Query(1,1,n,dfn[top[nde]],endp[nde]).mx);
146         }
147         if(nxt)
148         {
149             ss[nxt].insert(Query(1,1,n,dfn[top[nde]],endp[nde]).ll);
150             Ex(1,1,n,dfn[nxt],0),st.insert(Query(1,1,n,dfn[top[nxt]],endp[nxt]).mx);
151         }
152         nde=nxt;
153     }
154 }
155 void Change(int u,int v,int w)
156 {
157     int lca=LCA(u,v);
158     Modify(u,Query(1,1,n,dfn[top[u]],endp[u]).ll,lca,w);
159     Modify(v,Query(1,1,n,dfn[top[v]],endp[v]).ll,lca,w);
160     a x=Query(1,1,n,dfn[top[lca]],endp[lca]);
161     st.erase(st.lower_bound(x.mx)),Ex(1,1,n,dfn[lca],w);
162     st.insert(Query(1,1,n,dfn[top[lca]],endp[lca]).mx);
163     Modify(lca,x.ll,0,0);
164 }
165 int main()
166 {
167     Read(n),Read(m);
168     for(int i=1;i<n;i++) Read(t1),Read(t2),Link(t1,t2);
169     DFS(1,0,1),Mark(1,1);
170     for(int i=1;i<=m;i++)
171     {
172         scanf("%s",str);
173         if(str[0]=='+') 
174         {
175             Read(u[i]),Read(v[i]),Read(w[i]);
176             Change(u[i],v[i],w[i]);
177         }
178         else
179             Read(rd),Change(u[rd],v[rd],-w[rd]);
180         printf("%lld
",*st.rbegin());
181     }
182     return 0;
183 }
View Code

UOJ #207 共价大爷游长沙

日,发现自己的LCT写的又是假的

学习了LCT维护子树信息:记录一个所有轻儿子的信息合并进去,具体来说要改改Access和Link

一条路径被所有路径经过,当前仅当以一个端点为根时,所有路径的端点都恰好有一个在另一个的子树中

我们每次把两个端点异或一个随机数,同时记录所有随机数的全集异或和,每次查询子树里异或和即可

  1 #include<cstdio>
  2 #include<cctype>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int N=100005,M=300005;
  7 int n,m,t1,t2,t3,t4,typ,cnt,tot,fafa;
  8 int fth[N],son[N][2],rev[N],stk[N];
  9 int val[N],xors[N],lits[N],mem1[M];
 10 pair<int,int> mem2[M];
 11 void Read(int &x)
 12 {
 13     x=0; char ch=getchar();
 14     while(!isdigit(ch))
 15         ch=getchar();
 16     while(isdigit(ch))
 17         x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
 18 }
 19 void Write(int x)
 20 {
 21     if(x>9) Write(x/10);
 22     putchar(x%10^48);
 23 }
 24 int Rand()
 25 {
 26     return 1ll*rand()*rand()*rand()%2147483647;
 27 }
 28 void Pushup(int nde)
 29 {
 30     int lson=son[nde][0],rson=son[nde][1];
 31     xors[nde]=xors[lson]^xors[rson]^val[nde]^lits[nde];
 32 }
 33 void Release(int nde)
 34 {
 35     if(rev[nde])
 36     {
 37         int &lson=son[nde][0],&rson=son[nde][1];
 38         rev[lson]^=1,rev[rson]^=1,rev[nde]^=1;
 39         swap(lson,rson);
 40     }
 41 }
 42 bool Nottop(int nde)
 43 {
 44     int fa=fth[nde];
 45     return son[fa][0]==nde||son[fa][1]==nde;
 46 }
 47 void Rotate(int nde)
 48 {
 49     int fa=fth[nde],gr=fth[fa],isl=nde==son[fa][0];
 50     if(Nottop(fa)) son[gr][fa==son[gr][1]]=nde;
 51     fth[nde]=gr,fth[fa]=nde,fth[son[nde][isl]]=fa;
 52     son[fa][isl^1]=son[nde][isl],son[nde][isl]=fa;
 53     Pushup(fa),Pushup(nde);
 54 }
 55 void Splay(int nde)
 56 {
 57     int top=1; stk[top]=nde;
 58     for(int i=nde;Nottop(i);i=fth[i])
 59         stk[++top]=fth[i];
 60     while(top) Release(stk[top--]);
 61     while(Nottop(nde))
 62     {
 63         int fa=fth[nde],gr=fth[fa];
 64         if(Nottop(fa))
 65             Rotate(((son[fa][0]==nde)==(son[gr][0]==fa))?fa:nde);
 66         Rotate(nde);
 67     }
 68     Pushup(nde);
 69 }
 70 void Access(int nde)
 71 {
 72     int lst=0,mem=nde;
 73     while(nde)
 74     {
 75         Splay(nde);
 76         lits[nde]^=xors[son[nde][1]];
 77         lits[nde]^=xors[son[nde][1]=lst];
 78         Pushup(nde),lst=nde,nde=fth[nde];
 79     }
 80     Splay(mem);
 81 }
 82 void Turnroot(int nde)
 83 {
 84     Access(nde),rev[nde]^=1;
 85 }
 86 int Getroot(int nde)
 87 {
 88     Access(nde);
 89     while(son[nde][0])    
 90         nde=son[nde][0];
 91     Splay(nde);
 92     return nde;
 93 }
 94 void Split(int x,int y)
 95 {
 96     Turnroot(x),Access(y);
 97 }
 98 void Link(int x,int y)
 99 {
100     Split(x,y),fth[x]=y,lits[y]^=xors[x],Pushup(y);
101 }
102 void Cut(int x,int y)
103 {
104     Split(x,y),fth[x]=son[y][0]=0,Pushup(y);
105 }
106 int Query(int x,int y)
107 {
108     Cut(x,y),Access(y);
109     int ret=xors[y];
110     Link(x,y);
111     return ret;
112 }
113 void Change(int nde,int tsk)
114 {
115     Access(nde),val[nde]^=tsk,Pushup(nde);
116 }
117 int main()
118 {
119     srand(20020513);
120     Read(fafa),Read(n),Read(m);
121     for(int i=1;i<n;i++) 
122         Read(t1),Read(t2),Link(t1,t2);
123     while(m--)
124     {
125         Read(typ);
126         if(typ==1)
127         {
128             Read(t1),Read(t2),Read(t3),Read(t4);
129             Cut(t1,t2),Link(t3,t4);
130         }
131         else if(typ==2)
132         {
133             Read(t1),Read(t2),t3=Rand();
134             Change(t1,t3),Change(t2,t3);
135             tot^=t3,mem1[++cnt]=t3,mem2[cnt]=make_pair(t1,t2); 
136         }
137         else if(typ==3)
138         {
139             Read(t1),tot^=mem1[t1];
140             Change(mem2[t1].first,mem1[t1]);
141             Change(mem2[t1].second,mem1[t1]);
142         }
143         else 
144         {
145             Read(t1),Read(t2);
146             Query(t1,t2)==tot?puts("YES"):puts("NO");
147         }
148     }
149     return 0;
150 }
View Code

PA 2014 Fiolki

重构树,把所有步骤按时间连到虚点上,然后逆着扫求LCA,这样LCA深度越大的反应越早发生,模拟即可

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=400005,M=500005;
 6 struct a{int x,y,d,id;}sol[M];
 7 int n,m,k,t1,t2,cnt,tot; long long ans;
 8 int siz[N],anc[N],dep[N],imp[N],top[N];
 9 int p[N],noww[N<<1],goal[N<<1],bel[N],aset[N],g[N];
10 bool cmp(a x,a y)
11 {
12     return x.d==y.d?x.id<y.id:x.d>y.d;
13 }
14 int Finda(int x)
15 {
16     return aset[x]==x?x:aset[x]=Finda(aset[x]);
17 }
18 void Link(int f,int t)
19 {
20     noww[++cnt]=p[f];
21     goal[cnt]=t,p[f]=cnt;
22     noww[++cnt]=p[t];
23     goal[cnt]=f,p[t]=cnt;
24 }
25 void DFS(int nde,int fth,int dth)
26 {
27     int tmp=0;
28     siz[nde]=1,anc[nde]=fth,dep[nde]=dth;
29     for(int i=p[nde];i;i=noww[i])
30         if(goal[i]!=fth)
31         {
32             DFS(goal[i],nde,dth+1);
33             siz[nde]+=siz[goal[i]];
34             if(siz[goal[i]]>tmp)
35                 tmp=siz[goal[i]],imp[nde]=goal[i];
36         }
37 }
38 void MARK(int nde,int tpp)
39 {
40     top[nde]=tpp;
41     if(imp[nde])
42     {
43         MARK(imp[nde],tpp);
44         for(int i=p[nde];i;i=noww[i])
45             if(goal[i]!=anc[nde]&&goal[i]!=imp[nde])
46                 MARK(goal[i],goal[i]);
47     }
48 }
49 int LCA(int x,int y)
50 {
51     while(top[x]!=top[y])
52     {
53         if(dep[top[x]]<dep[top[y]])
54             swap(x,y); x=anc[top[x]];
55     }
56     return dep[x]<dep[y]?x:y;
57 }
58 int main ()
59 {
60     scanf("%d%d%d",&n,&m,&k);
61     for(int i=1;i<=n;i++) 
62         scanf("%d",&g[i]),bel[i]=i,aset[i]=i;
63     for(int i=1;i<=m;i++)
64     {
65         scanf("%d%d",&t1,&t2);
66         Link(bel[t1],i+n),Link(bel[t2],i+n);
67         bel[t2]=i+n,aset[Finda(t1)]=Finda(t2);
68     }
69     for(int i=n+m;i;i--)
70         if(!siz[i]) DFS(i,0,1),MARK(i,i);
71     for(int i=1;i<=k;i++)
72     {
73         scanf("%d%d",&t1,&t2);
74         if(Finda(t1)==Finda(t2))
75             sol[++tot]=(a){t1,t2,dep[LCA(t1,t2)],i};
76     }
77     sort(sol+1,sol+1+tot,cmp);
78     for(int i=1;i<=tot;i++)
79     {
80         int tx=sol[i].x,ty=sol[i].y,mn=min(g[tx],g[ty]);
81         g[tx]-=mn,g[ty]-=mn,ans+=2*mn;
82     }
83     printf("%lld",ans);
84     return 0;
85 }
View Code

PA 2014 Druzyny

线线线段段段树树树题

什么,我的题解?去看这位神仙的吧

卡时空好题,加上BZOJ的评测机加持,刺激

我这份代码卡着时空过的,如有需要请自行使用快读替换scanf等操作

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 const int N=1e6+10,M=4e6+20;
  6 const int inf=1e9,mod=1e9+7;
  7 int n,f,b,p,c[N],d[N],que[N],lpt[N],maxc[M];
  8 struct a
  9 {
 10     int opt,val;
 11 }dp[N],seg[M],laz[M];
 12 a Re(const a &x){return (a){x.opt+1,x.val};}
 13 void Add(int &x,int y){x+=y;if(x>=mod) x-=mod;}
 14 a operator + (a x,a y)
 15 {
 16     if(x.opt!=y.opt) return x.opt>y.opt?x:y;
 17     else {Add(x.val,y.val); return x;}
 18 }
 19 void Create2(int nde,int l,int r)
 20 {
 21     if(l==r)
 22         maxc[nde]=l;
 23     else
 24     {
 25         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
 26         Create2(ls,l,mid),Create2(rs,mid+1,r);
 27            maxc[nde]=(c[maxc[ls]]<c[maxc[rs]])?maxc[rs]:maxc[ls];
 28     }
 29 }
 30 int Query2(int nde,int l,int r,int ll,int rr)
 31 {
 32     if(l>rr||r<ll)
 33         return 0;
 34     else if(l>=ll&&r<=rr)
 35         return maxc[nde];
 36     else
 37     {
 38         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
 39         int r1=Query2(ls,l,mid,ll,rr);
 40         int r2=Query2(rs,mid+1,r,ll,rr);
 41         return c[r1]<c[r2]?r2:r1; 
 42     }
 43 }
 44 void Create3(int nde,int l,int r)
 45 {
 46     if(l==r)
 47         seg[nde]=dp[l],laz[nde]=(a){-inf,0};
 48     else
 49     {
 50         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
 51         Create3(ls,l,mid),Create3(rs,mid+1,r);
 52         seg[nde]=seg[ls]+seg[rs],laz[nde]=laz[ls]+laz[rs];
 53     }
 54 }
 55 void Change3(int nde,int l,int r,int pos,a tsk)
 56 {
 57     if(l==r)
 58         seg[nde]=tsk;
 59     else
 60     {
 61         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
 62         if(pos<=mid) Change3(ls,l,mid,pos,tsk);
 63         else Change3(rs,mid+1,r,pos,tsk);
 64         seg[nde]=seg[ls]+seg[rs];
 65     }
 66 } 
 67 void Add3(int nde,int l,int r,int ll,int rr,a tsk)
 68 {
 69     if(l>rr||r<ll)
 70         return ;
 71     else if(l>=ll&&r<=rr)
 72         laz[nde]=laz[nde]+tsk;
 73     else
 74     {
 75         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
 76         Add3(ls,l,mid,ll,rr,tsk),Add3(rs,mid+1,r,ll,rr,tsk);    
 77     }
 78 } 
 79 a Query3(int nde,int l,int r,int pos)
 80 {
 81     a ret=(a){-inf,0};
 82     while(true)
 83     {
 84         ret=ret+laz[nde];
 85         if(l==r) return ret;
 86         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
 87         if(pos<=mid) nde=ls,r=mid; else nde=rs,l=mid+1;
 88     }
 89     return ret;
 90 }
 91 a Query4(int nde,int l,int r,int ll,int rr)
 92 {
 93     if(l>rr||r<ll)
 94         return (a){-inf,0};
 95     else if(l>=ll&&r<=rr)
 96         return seg[nde];
 97     else
 98     {
 99         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
100         return Query4(ls,l,mid,ll,rr)+Query4(rs,mid+1,r,ll,rr); 
101     }
102 }
103 int BS(int l,int r,int x)
104 {
105     int ret=0;
106     while(l<=r)
107     {
108         int mid=(l+r)/2;
109         if(lpt[mid]<=x) l=mid+1,ret=mid;
110         else r=mid-1;
111     }
112     return ret;
113 }
114 void Solve(int l,int r,int k)
115 {
116     int mid=max(k,l+c[k]),ll=max(l,lpt[mid]),rr=min(k-1,mid-c[k]); 
117     if(r<mid||k<=ll) return ;
118     a qry=Query4(1,0,n,ll,rr); 
119     while(ll<=l&&mid<=r)
120     {
121         if(k-1<=rr) 
122         {
123             int newr=BS(mid,r,l); 
124             Add3(1,0,n,mid,newr,Re(qry)),mid=newr+1;
125             break;
126         }
127         dp[mid]=dp[mid]+Re(qry);
128         qry=qry+dp[++rr],ll=max(ll,lpt[++mid]);
129     }
130     while(mid<=r)
131     {
132         ll=lpt[mid],rr=min(k-1,mid-c[k]);
133         if(k<ll) return ;
134         a qur=Query4(1,0,n,ll,rr); 
135         qur.opt++,dp[mid]=dp[mid]+qur,mid++;
136     }
137 }
138 void Divide(int l,int r)
139 {
140     if(l>r) return;
141     else if(l==r) 
142     {
143         dp[l]=dp[l]+Query3(1,0,n,l);
144         Change3(1,0,n,l,dp[l]); return ;
145     }
146     else
147     {
148         int mid=Query2(1,0,n,l+1,r);
149         Divide(l,mid-1),Solve(l,r,mid),Divide(mid,r);
150     }
151 }
152 int main()
153 {
154     scanf("%d",&n),f=0,b=-1;
155     for(int i=1;i<=n;i++)
156         scanf("%d%d",&c[i],&d[i]);
157     for(int i=1;i<=n;dp[i].opt=-inf,i++)
158     {
159         lpt[i]=lpt[i-1];
160         while(f<=b&&d[i]<=d[que[b]]) b--;
161         que[++b]=i;
162         while(f<=b&&d[que[f]]+lpt[i]<i)
163             f+=que[f]==lpt[i]+1,lpt[i]++; 
164     }
165     dp[0].val=1;
166     Create2(1,0,n),Create3(1,0,n),Divide(0,n);
167     (dp[n].opt>0)?printf("%d %d",dp[n].opt,dp[n].val):printf("NIE");
168     return 0;
169 } 
View Code

SCOI 2016 萌萌哒

显然是并查集数联通块数cnt,然后答案是$9*10^{cnt-1}$(最高位填1-9,剩下的填0-9)

ST表的思想,令$aset[i][j]$表示$[i,i+2^j-1]$这一块的连通性,递归合并,注意剪枝

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=100005,K=19,mod=1e9+7;
 7 int n,m,l1,l2,t1,t2,t3,t4,len,ans,aset[K][N];
 8 int Qpow(int x,int k)
 9 {
10     if(k==1) return x;
11     int tmp=Qpow(x,k/2);
12     return k%2?1ll*tmp*tmp%mod*x%mod:1ll*tmp*tmp%mod;
13 }
14 int Finda(int o,int x)
15 {
16     return aset[o][x]==x?x:aset[o][x]=Finda(o,aset[o][x]);
17 }
18 void Merge(int a,int b,int k)
19 {
20     int f1=Finda(k,a),f2=Finda(k,b),len=1<<(k-1);
21     aset[k][f1]=f2; if(!k||f1==f2) return; 
22     Merge(a,b,k-1),Merge(a+len,b+len,k-1);
23 }
24 int main()
25 {
26     scanf("%d%d",&n,&m),l1=log2(n);
27     for(int i=0;i<=l1;i++)
28         for(int j=1;j<=n;j++)
29             aset[i][j]=j;
30     for(int i=1;i<=m;i++)
31     {
32         scanf("%d%d%d%d",&t1,&t2,&t3,&t4);
33         if(t1>t3) swap(t1,t3),swap(t2,t4);
34         l2=log2(t2-t1+1),len=(1<<l2)-1;
35         Merge(t1,t3,l2),Merge(t2-len,t4-len,l2);
36     }
37     for(int i=1;i<=n;i++)
38         if(Finda(0,i)==i) ans++;
39     printf("%lld",9ll*Qpow(10,ans-1)%mod);
40     return 0;
41 }
View Code

SCOI 2016 美味

从高位向低位贪心,在主席树上二分找加上偏移量之后的区间里有没有值,有就贪心拿这一位

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=200005,inf=1e9,Maxx=(1<<18)-1;
 6 int n,m,t1,t2,t3,t4,tot;
 7 int dish[N],root[N],cnt[N*40],son[N*40][2];
 8 int Insert(int pre,int l,int r,int pos)
 9 {
10     int nde=++tot;
11     son[nde][0]=son[pre][0];
12     son[nde][1]=son[pre][1];
13     cnt[nde]=cnt[pre]+1;
14     if(l!=r)
15     {
16         int mid=(l+r)>>1;
17         if(pos<=mid) 
18             son[nde][0]=Insert(son[pre][0],l,mid,pos);
19         else 
20             son[nde][1]=Insert(son[pre][1],mid+1,r,pos);
21     }
22     return nde;
23 }
24 int Query(int l,int r,int nl,int nr,int ll,int rr)
25 {
26     if(l>rr||r<ll) 
27         return 0;
28     else if(l>=ll&&r<=rr) 
29         return cnt[nr]-cnt[nl];    
30     else
31     {
32         int mid=(l+r)>>1;
33         int r1=Query(l,mid,son[nl][0],son[nr][0],ll,rr);
34         int r2=Query(mid+1,r,son[nl][1],son[nr][1],ll,rr);
35         return r1+r2;
36     }
37 }
38 int Ask(int l,int r,int ll,int rr,int k,int a,int b)
39 {
40     if(l==r) return a^l;
41     int mid=(l+r)>>1;
42     if(a&(1<<(k-1)))
43     {
44         int qry=Query(0,Maxx,ll,rr,max(l-b,0),max(mid-b,0));
45         return qry?Ask(l,mid,ll,rr,k-1,a,b):Ask(mid+1,r,ll,rr,k-1,a,b);
46     }
47     else
48     {
49         int qry=Query(0,Maxx,ll,rr,max(mid+1-b,0),max(r-b,0));
50         return qry?Ask(mid+1,r,ll,rr,k-1,a,b):Ask(l,mid,ll,rr,k-1,a,b);    
51     }
52 }
53 int main()
54 {
55     scanf("%d%d",&n,&m);
56     for(int i=1;i<=n;i++)
57     {
58         scanf("%d",&dish[i]);
59         root[i]=Insert(root[i-1],0,Maxx,dish[i]);
60     }
61     while(m--)
62     {
63         scanf("%d%d%d%d",&t1,&t2,&t3,&t4);
64           printf("%d
",Ask(0,Maxx,root[t3-1],root[t4],18,t1,t2));
65     }
66     return 0;
67 }
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/10383998.html