咕咕咕。按上傳時間升序排列。node
//樹的重心 void dfs(int x) { v[x]=1; size[x]=1; int max_part=0; for(int i=hed[x];i;i=nxt[i]) { int y=ver[i]; if(v[y]) continue; dfs(y); size[x]+=size[y]; max_part=max(max_part,size[y]); } max_part=max(max_part,n-size[x]); if(max_part<ans) { ans=max_part; ans_node=x; } }
//推箱子,沒AC #include<bits/stdc++.h> using namespace std; const int maxn=31; char s[maxn][maxn]; int n,m; struct node{ int x,y,dir; }st[7],ed[7]; int stcnt,edcnt; struct node2{ int x,y; }manst; int dx[4]={-1,1,0,0}; int dy[4]={0,0,-1,1}; int ddir[4]={1,0,3,2}; node pre_box[maxn][maxn][4]; int min_box[maxn][maxn][4],min_man[maxn][maxn][4]; bool valid(int x,int y) { if(x<1||x>n||y<1||y>m) return false; return s[x][y]=='#' ? false : true; } bool connect(int r,int c)//man to r,c { int vis[maxn][maxn]={0}; vis[manst.x][manst.y]=1; queue<node2>q; q.push(manst); while(!q.empty()) { node2 u=q.front();q.pop(); if(u.x==r&&u.y==c) return true; for(int i=0;i<4;++i) { node2 v=(node2){u.x+dx[i],u.y+dy[i]}; if(!valid(v.x,v.y)||vis[v.x][v.y]) continue; q.push(v); vis[v.x][v.y]=1; } } return false; } void findsted() { stcnt=edcnt=0; for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) { if(s[i][j]=='S') { s[i][j]='.'; manst.x=i,manst.y=j; } if(s[i][j]=='T') { s[i][j]='.'; for(int D=0;D<4;++D) { if(valid(i+dx[D],j+dy[D])) { ed[++edcnt]=(node){i,j,D}; } } } } for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) { if(s[i][j]=='B') { s[i][j]='.'; for(int D=0;D<4;++D) { if(valid(i+dx[D],j+dy[D])) { s[i][j]='#'; if(connect(i+dx[D],j+dy[D])) st[++stcnt]=(node){i,j,D}; s[i][j]='.'; } } } } } int getstep(node U,node V) { node2 S=(node2){U.x+dx[U.dir],U.y+dy[U.dir]}; node2 T=(node2){U.x+dx[V.dir],U.y+dy[V.dir]}; int step[maxn][maxn]; memset(step,-1,sizeof step); queue<node2>q; q.push(S); step[S.x][S.y]=0; while(!q.empty()) { node2 u=q.front();q.pop(); if(u.x==T.x&&u.y==T.y) return step[u.x][u.y]; for(int i=0;i<4;++i) { node2 v=(node2){u.x+dx[i],u.y+dy[i]}; if(!valid(v.x,v.y)||step[v.x][v.y]!=-1) continue; q.push(v); step[v.x][v.y]=step[u.x][u.y]+1; } } return -1; } int getstep(node2 U,node V) { node2 T=(node2){V.x+dx[V.dir],V.y+dy[V.dir]}; int step[maxn][maxn]; memset(step,-1,sizeof step); queue<node2>q; q.push(U); step[U.x][U.y]=0; while(!q.empty()) { node2 u=q.front();q.pop(); if(u.x==T.x&&u.y==T.y) return step[u.x][u.y]; for(int i=0;i<4;++i) { node2 v=(node2){u.x+dx[i],u.y+dy[i]}; if(!valid(v.x,v.y)||step[v.x][v.y]!=-1) continue; q.push(v); step[v.x][v.y]=step[u.x][u.y]+1; } } return -1; } bool is_ans(node u) { for(int i=1;i<=edcnt;++i) if(ed[i].x==u.x&&ed[i].y==u.y&&ed[i].dir==u.dir) return true; return false; } int solve() { int jd=-1; memset(min_box,63,sizeof min_box); memset(min_man,63,sizeof min_man); queue<node>q; for(int i=1;i<=stcnt;++i) { q.push(st[i]); min_box[st[i].x][st[i].y][st[i].dir]=0; s[st[i].x][st[i].y]='#'; min_man[st[i].x][st[i].y][st[i].dir]=getstep(manst,st[i]); s[st[i].x][st[i].y]='.'; pre_box[st[i].x][st[i].y][st[i].dir].x=0; } while(!q.empty()) { node u=q.front();q.pop(); // printf("u(%d,%d)\n",u.x,u.y); if(is_ans(u)) jd=1; for(int i=0;i<4;++i) { node v=(node){u.x+dx[i],u.y+dy[i],ddir[i]}; if(!valid(v.x,v.y) || !valid(u.x+dx[v.dir],u.y+dy[v.dir])) continue; if(min_box[u.x][u.y][u.dir]+1>min_box[v.x][v.y][v.dir]) continue; s[u.x][u.y]='#'; int step=getstep(u,v); s[u.x][u.y]='.'; if(step==-1) continue; if(min_box[u.x][u.y][u.dir]+1==min_box[v.x][v.y][v.dir]&& min_man[u.x][u.y][u.dir]+step>min_man[v.x][v.y][v.dir]) continue; min_box[v.x][v.y][v.dir]=min_box[u.x][u.y][u.dir]+1; min_man[v.x][v.y][v.dir]=min_man[u.x][u.y][u.dir]+step; pre_box[v.x][v.y][v.dir]=u; q.push(v); } } return jd; } void putlina(int ind) { switch(ind) { case 0:cout<<'s';break; case 1:cout<<'n';break; case 2:cout<<'e';break; case 3:cout<<'w';break; } } void putlinA(int ind) { switch(ind) { case 0:cout<<'S';break; case 1:cout<<'N';break; case 2:cout<<'E';break; case 3:cout<<'W';break; } } void road(int sx,int sy,int ex,int ey) { int pre[maxn][maxn]; memset(pre,-1,sizeof pre); pre[sx][sy]=-2; queue<node2>q; q.push((node2){sx,sy}); while(!q.empty()) { node2 u=q.front(); q.pop(); if(u.x==ex&&u.y==ey) { stack<int>sta; while(pre[u.x][u.y]!=-2) { sta.push(pre[u.x][u.y]); int d=pre[u.x][u.y];// u.x+=dx[d], u.y+=dy[d]; } while(!sta.empty()) { putlina(sta.top()); sta.pop(); } return; } for(int i=0;i<4;++i) { node2 v=(node2){u.x+dx[i],u.y+dy[i]}; if(!valid(v.x,v.y)) continue; if(pre[v.x][v.y]!=-1) continue; q.push(v); pre[v.x][v.y]=ddir[i]; } } } void out() { stack<node>sta; int boxx=1010010101,mann=1010010101,i; for(int j=1;j<=edcnt;++j) if(min_box[ed[j].x][ed[j].y][ed[j].dir]<boxx || min_box[ed[j].x][ed[j].y][ed[j].dir]==boxx&&min_man[ed[j].x][ed[j].y][ed[j].dir]<mann) { boxx=min_box[ed[j].x][ed[j].y][ed[j].dir]; mann=min_man[ed[j].x][ed[j].y][ed[j].dir]; i=j; } node u=ed[i]; while(u.x) sta.push(u), u=pre_box[u.x][u.y][u.dir]; vector<node>vec; while(!sta.empty()) { vec.push_back(sta.top()); sta.pop(); } s[st[1].x][st[1].y]='#'; road(manst.x,manst.y,vec[0].x+dx[vec[1].dir],vec[0].y+dy[vec[1].dir]); s[st[1].x][st[1].y]='.'; putlinA(vec[1].dir); for(int k=2;k<(int)vec.size();++k) { s[vec[k-1].x][vec[k-1].y]='#'; road(vec[k-1].x+dx[vec[k-1].dir],vec[k-1].y+dy[vec[k-1].dir],vec[k-1].x+dx[vec[k].dir],vec[k-1].y+dy[vec[k].dir]); s[vec[k-1].x][vec[k-1].y]='.'; putlinA(vec[k].dir); } return; } int main() { int T=0; while(scanf("%d%d",&n,&m)==2 && n) { memset(s,0,sizeof s); for(int i=1;i<=n;++i) scanf("%s",s[i]+1); findsted(); printf("Maze #%d\n",++T); if(solve()==-1) printf("Impossible.\n\n"); else out(),printf("\n\n"); } }
//食物鏈 #include<bits/stdc++.h> using namespace std; const int maxn=50005; int fa[maxn*3]; int n,k,ans; int fid(int x) {return fa[x]==x ? x : fa[x]=fid(fa[x]);} void merge(int i,int j) { i=fid(i),j=fid(j); fa[i]=j; } int main() { scanf("%d%d",&n,&k); for(int i=1;i<=3*n;++i) fa[i]=i; for(int i=1;i<=k;++i) { int d,x,y; scanf("%d%d%d",&d,&x,&y); if(x>n||y>n) {ans++;continue;} int x_a=x,x_b=x+n,x_c=x+n+n; int y_a=y,y_b=y+n,y_c=y+n+n; if(d==1) { //jd int lowe=(fid(x_a)==fid(y_b))||(fid(x_b)==fid(y_c))||(fid(x_c)==fid(y_a)); int uppe=(fid(y_a)==fid(x_b))||(fid(y_b)==fid(x_c))||(fid(y_c)==fid(x_a)); if(lowe||uppe) {ans++;continue;} //make merge(x_a,y_a); merge(x_b,y_b); merge(x_c,y_c); } else { //jd if(x==y) {ans++;continue;} int case1=(fid(y_a)==fid(x_b))||(fid(y_b)==fid(x_c))||(fid(y_c)==fid(x_a)); int case2=(fid(x_a)==fid(y_a))||(fid(x_b)==fid(y_b))||(fid(x_c)==fid(y_c)); if(case1||case2) {ans++;continue;} //make merge(x_a,y_b); merge(x_b,y_c); merge(x_c,y_a); } } cout<<ans; return 0;
//小trick……樹狀數組O(n)初始化,原理是每一個以i爲標號的節點的值爲其子節點的值之和與$a_i$的值的和 void init() { for(int i=1;i<=n;++i) { t[i]+=a[i]; int j;if(j=i+lowbit(i)<=n) t[j]+=t[i]; } } //大trick:樹狀數組區間加法、區間求和(爛大街) void add(int x,int val) { for(int i=x;i<=n;i-=lowbit(i)) { d1[i]+=val; d2[i]+=val*x; } } int ask(int x) { int res=0; for(int i=x;i>=1;i-=lowbit(i)) { res+=(x+1)*d1[i]; res+=d2[i]; } return res } //小trick:權值樹狀數組查詢kth(樹狀數組上倍增)(O (log n)) int kth(int k) { int cnt=0,ret=0; for(int i=log2(n);~i;--i) { ret+=1<<i; if(ret>=n||cnt+t[ret]>=k) ret-=1<<i; else cnt+=t[ret]; } return ret + 1; }
//權值樹狀數組上倍增(謎通常的牛) #include<bits/stdc++.h> using namespace std; const int maxn=100005; int t[maxn],n,a[maxn]; int ans[maxn]; int que(int k) { int ret=0,sum=0; for(int i=log2(n)+1;~i;--i) { if(ret+(1<<i)<=n && sum+t[ret+(1<<i)]<k) sum+=t[ret+(1<<i)], ret+=1<<i; } return ret+1; } void del(int x) { for(int i=x;i<=n;i+=i&-i) { t[i]--; } } int main() { scanf("%d",&n); for(int i=2;i<=n;++i) scanf("%d",&a[i]); a[1]=0; for(int i=1;i<=n;++i) { t[i]+=1; int j=i+(i&-i); if(j<=n) t[j]+=t[i]; } for(int i=n;i>=1;--i) { ans[i]=que(a[i]+1); del(ans[i]); } for(int i=1;i<=n;++i) cout<<ans[i]<<'\n'; return 0; }
//kruskal最小生成樹算法板子(O(m log m)) struct rec{int x,y,z;}edge[500010]; int fa[100010],n,m,ans; bool operator < (rec a,rec b) { return a.z<b.z; } int get(int x) { if(fa[x]==x) return x; return fa[x]=get(fa[x]); } int main() { cin>> n >> m; for(int i=1;i<=m;++i) scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z); sort(edge+1,edge+1+m); for(int i=1;i<=n;++i) fa[i]=i; for(int i=1;i<=m;++i) { int x=get(edge[i].x); int y=get(edge[i].y); if(x==y) continue; fa[x]=y; ans+=edge[i].z; } cout<<ans; return 0; }
//堆優化 prim 最小生成樹(抄別人的代碼,這馬蜂我受不了啊) struct node{ int t;int d; bool operator < (const node &a) const { return !(d<a.d); } }; int n,m; int vis[maxn]; vector<node>e[maxn]; priority_queue<node>q; ll pirm() { ll ans=0; int cnt=0; q.push((node){1,0}); while(!q.empty()&&cnt<=n) { node k=q.top(); q.pop(); if(vis[k]) continue; vis[k]=1; ans+=k.d; cnt++; for(int i=0;i<e[k.t].size();++i) { if(!vis[e[k.t][i].t]) { q.push((node){e[k.t][i].t,e[k.t][i].d}) } } } return ans; }
//最短路鬥筆題,9.29被卡智商了,看來這幾天智商仍是有提升的。(It's not a bug, it's a feature!(Uva658)) #include<bits/stdc++.h> using namespace std; struct fix{ char pre[21],nxt[21]; int t; }fixs[111]; int n,m; long long d[(1<<20)+5]; bool vis[(1<<20)+5]; struct heapnode{ int t, bugstyle; }; bool operator <(heapnode a,heapnode b) { return !(a.t<b.t); } int solve() { priority_queue<heapnode>q; q.push((heapnode){0, (1<<n)-1}); for(int i=0;i<=(1<<n)-1;++i) d[i]=2147483647; d[(1<<n)-1]=0; memset(vis,0,sizeof vis); while(!q.empty()) { heapnode u=q.top(); q.pop(); if(vis[u.bugstyle]) continue; vis[u.bugstyle]=1; for(int i=1;i<=m;++i) { bool canbeput = true; for(int j=0;j<n;++j) if(fixs[i].pre[j]=='+'&& !(u.bugstyle & (1<<j))) {canbeput=false; break;} for(int j=0;j<n;++j) if(fixs[i].pre[j]=='-'&& (u.bugstyle & (1<<j))) {canbeput=false; break;} if(!canbeput) continue; heapnode v=(heapnode) {fixs[i].t+d[u.bugstyle],u.bugstyle}; for(int j=0;j<n;++j) { if(fixs[i].nxt[j]=='+') {v.bugstyle |= (1<<j);} if(fixs[i].nxt[j]=='-') {v.bugstyle &= ~(1<<j);} } if(d[v.bugstyle]>v.t) { d[v.bugstyle]=v.t; q.push(v); } } } if(d[0]==2147483647) return -1; else return d[0]; } int main() { int id=0; while(scanf("%d%d",&n,&m)==2&& n|m) { for(int i=1;i<=m;++i) scanf("%d%s%s",&fixs[i].t,fixs[i].pre,fixs[i].nxt); printf("Product %d\n",++id); int ans=solve(); if(ans<0) printf("Bugs cannot be fixed.\n\n"); else printf("Fastest sequence takes %d seconds.\n\n",ans); } return 0; }
//聯通塊間最短路(BZOJ2200) #include<bits/stdc++.h> using namespace std; const int maxn=25005; const int maxm=50005; int t,r,p,s; int cnt,c[maxn], deg[maxn]; int ct,ver[maxm<<2],val[maxm<<2],hed[maxm<<2],nxt[maxm<<2]; void add(int a,int b,int c) { ver[++ct]=b; val[ct]=c; nxt[ct]=hed[a]; hed[a]=ct; } void tag_it(int u) { c[u]=cnt; for(int i=hed[u];i;i=nxt[i]) { int v=ver[i]; if(c[v]) continue; tag_it(v); } } void get_c() { for(int i=1;i<=t;++i) if(!c[i]) {cnt++;tag_it(i);} } int vis[maxn]; long long d[maxn]; void dij(int block,queue<int> &buff); void topo_sort_and_dij() { queue<int> buff; for(int i=1;i<=cnt;++i) if(!deg[i]) buff.push(i); while(!buff.empty()) { int u=buff.front(); buff.pop(); dij(u,buff); } } struct heapnode{ long long d; int x; }; bool operator <(heapnode a,heapnode b) { return !(a.d<b.d); } void dij(int block,queue<int> &buff) { priority_queue<heapnode>Q; for(int i=1;i<=t;++i) if(c[i]==block) Q.push((heapnode){d[i],i}); while(!Q.empty()) { int u=Q.top().x; Q.pop(); if(vis[u]) continue; else vis[u]=true; for(int i=hed[u];i;i=nxt[i]) { int v=ver[i]; if(d[v]>d[u]+val[i]) { d[v]=d[u]+val[i]; if(c[u]==c[v]) Q.push((heapnode){d[v],v}); } if(c[u]!=c[v]) { deg[c[v]]--; if(!deg[c[v]]) buff.push(c[v]); } } } } void out_ans() { for(int i=1;i<=t;++i) if(d[i]>=2000000000) printf("NO PATH\n"); else printf("%lld\n",d[i]); } int main() { scanf("%d%d%d%d",&t,&r,&p,&s); for(int i=1;i<=r;++i) {int a,b,z; scanf("%d%d%d",&a,&b,&z);add(a,b,z); add(b,a,z);} get_c(); for(int i=1;i<=p;++i) {int a,b,z; scanf("%d%d%d",&a,&b,&z);add(a,b,z); deg[c[b]]++;} for(int i=1;i<=t;++i) d[i]=2147483647; d[s]=0; topo_sort_and_dij(); out_ans(); return 0; }
//Bellman-Ford的隊列優化 bool bellman_ford() { queue<int>Q; memset(inq,0,sizeof inq); memset(cnt,0,sizeof cnt); for(int i=1;i<=n;++i) d[i] = INF; d[start]=0; q.push(start); inq[start] = true; while(!q.empty()) { int u=q.front(); q.pop(); inq[u] = false; for(int i=0;i<(int)G[u].size();++i) { Edge& e=edges[G[u][i]]; if(d[u]<INF && d[e.to]>d[u]+e.dist) { d[e.to]=d[u]+e.dist; if(!inq[e.to]) {Q.push(e.to); inq[e.to]=true; if(++cnt[e.to]>n) return false; } } } } return true; }
//floyed板子 int d[310][310], n, m; int main() { cin >> n >> m; memset(d, 0x3f, sizeof d); for(int i=1;i<=n;++i) d[i][i]=0; for(int i=1;i<=m;++i) { int x,y,z; scanf("%d%d%d",&x,&y,&z); d[x][y]=min(d[x][y],z); } for(int k=1;k<=n;++k) for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) d[i][j]=min(d[i][j],d[i][k]+d[k][j]); }
int era(int *primes,int lim) // 求1-n的全部素數,保存在primes裏,返回primes中的素數個數。 { int v[maxlim]={0}, cnt=0; int m=sqrt(lim+0.5); for(int i=2;i<=m;++i) if(!vis[i]) { primes[++cnt]=i; for(int j=i*i;j<=lim;j+=i) v[j]=1; } return cnt; }
//試除法求n的正約數集合 int factor[1010], m=0; for(int i=1;i*i<=n;++i) { if(n%i==0) { factor[++m]=i; if(n/i != i) factor[++m]=n/i; } }
//倍數法求1-n的正約數集合 vector<int>factor[70707]; for(int i=1;i<=n;++i) for(int j=i;j<=n;j+=i) factor[j].push_back(i);
//超大常數的線段樹qwq #include<bits/stdc++.h> using namespace std; const int maxn=100005; struct SegTree{ int l,r; long long sum,tag; #define l(x) tree[x].l #define r(x) tree[x].r #define sum(x) tree[x].sum #define tag(x) tree[x].tag }tree[maxn<<2]; long long a[maxn]; int m,n; void build(int p,int l,int r) { l(p)=l, r(p)=r; if(l==r) {sum(p)=a[l];return;} int mid=(l+r)>>1; build(p<<1,l,mid),build(p<<1|1,mid+1,r); sum(p)=sum(p<<1)+sum(p<<1|1); } void pushdown(int p) { if(tag(p)) { sum(p<<1)+=tag(p)*(r(p<<1)-l(p<<1)+1),sum(p<<1|1)+=tag(p)*(r(p<<1|1)-l(p<<1|1)+1); tag(p<<1)+=tag(p),tag(p<<1|1)+=tag(p); tag(p)=0; } } void chan(int p,int l,int r,long long k) { if(l<=l(p)&&r>=r(p)) {sum(p)+=k*(r(p)-l(p)+1);tag(p)+=k;return;} pushdown(p); int mid=(l(p)+r(p))>>1; if(l<=mid) chan(p<<1,l,r,k); if(r>mid) chan(p<<1|1,l,r,k); sum(p)=sum(p<<1)+sum(p<<1|1); } long long ask(int p,int l,int r) { if(l<=l(p)&&r>=r(p)) {return sum(p);} pushdown(p); int mid=(l(p)+r(p))>>1; long long val=0; val = (l<=mid) ? val+ask(p<<1,l,r) : val; val = (r>mid) ? val+=ask(p<<1|1,l,r) : val; return val; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) scanf("%lld",&a[i]); build(1,1,n); while(m--) { int op,l,r; scanf("%d%d%d",&op,&l,&r); if(op==1) { long long k;scanf("%lld",&k); chan(1,l,r,k); } else { cout<<ask(1,l,r)<<'\n'; } } return 0; }
//掃描線求矩形面積 //maxn*2 line //maxn*2 row //maxn*8 c #include<bits/stdc++.h> using namespace std; const int maxn=100005; int n; struct line{ int x,yup,ydown,val; }lines[maxn<<2]; int linecnt; //lines int pre[maxn<<2],precnt,row[maxn<<2],Cnt; //row long long ans=0; void solve(); int main() { scanf("%d",&n); for(int i=1;i<=n;++i) { int xleft,xright,yup,ydown; scanf("%d%d%d%d",&xleft,&ydown,&xright,&yup); lines[++linecnt]=(line){xleft,yup,ydown,1}; lines[++linecnt]=(line){xright,yup,ydown,-1}; pre[++precnt]=yup; pre[++precnt]=ydown; } sort(pre+1,pre+precnt+1); pre[0]=-1; for(int i=1;i<=precnt;++i) if(pre[i]!=pre[i-1]) row[++Cnt]=pre[i]; for(int i=1;i<=linecnt;++i) lines[i].yup=lower_bound(row+1,row+1+Cnt,lines[i].yup)-row, lines[i].ydown=lower_bound(row+1,row+1+Cnt,lines[i].ydown)-row; solve(); return 0; } struct SegTree { int l,r; int cnt,len; #define l(x) tree[x].l #define r(x) tree[x].r #define cnt(x) tree[x].cnt #define len(x) tree[x].len }tree[maxn<<4]; void build(int p,int l,int r) { l(p)=l, r(p)=r; if(l==r) return; int mid=(l+r)>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r); } inline void pushup(int p) { if(cnt(p)) len(p)=row[r(p)+1]-row[l(p)]; else len(p)=len(p<<1)+len(p<<1|1); } void ins(int p,int l,int r,int val) { if(l<=l(p)&&r>=r(p)) {cnt(p)+=val;pushup(p);return;} int mid=(l(p)+r(p))>>1; if(l<=mid) ins(p<<1,l,r,val); if(r>mid) ins(p<<1|1,l,r,val); pushup(p); } bool cmp(line a,line b) { return a.x<b.x; } void solve() { build(1,1,Cnt-1); sort(lines+1,lines+1+linecnt,cmp); for(int i=1;i<=linecnt;++i) { ans+=(long long)len(1)*(lines[i].x-lines[i-1].x); ins(1,lines[i].ydown,lines[i].yup-1,lines[i].val); } cout<<ans; return; }
//動態開點線段樹 struct SegTree { int lc,rc; int dat; }tr[size*2]; int root,tot; int build() { tot++; tr[tot].dat=tr[tot].lc=tr[tot].rc=0; return tot; } void ins(int p,int l,int r,int val,int delta) { if(l==r) { tr[p].dat+=delta; return; } int mid=(l+r)>>1; if(val<=mid) { if(!tr[p].lc) tr[p].lc-build(); ins(tr[p].lc,l,mid,val,delta); } else { if(!tr[p].rc) tr[p].rc=build(); ins(tr[p].rc,mid+1,r,val,delta); } tr[p].dat=max(tr[tr[p].lc].dat,tr[tr[p].rc].dat); } ins(root,1,n,val,delta);
//將以q爲根的線段樹合併到以p爲根的線段樹上 int merge(int p,int q,int l,int r) { if(!p||!q) return p+q; if(l==r) { tr[p].dat+=tr[q].dat; return p; } int mid=(l+r)>>1; tr[p].lc=merge(tr[p].lc,tr[q].lc,l,mid); tr[p].rc=merge(tr[p].rc,tr[q].rc,mid+1,r); tr[p].dat=max(tr[tr[p].lc].dat,tr[tr[p].rc].dat); return p; }
//普通平衡樹,樹狀數組寫法(離線) #include<bits/stdc++.h> using namespace std; const int maxn=100005; int n; int opt[maxn],x[maxn]; int row[maxn],cnt; int t[maxn]; void ins(int x) { for(int i=x;i<=cnt;i+=i&-i) ++t[i]; } void del(int x) { for(int i=x;i<=cnt;i+=i&-i) --t[i]; } int que(int x) { int ret=0; for(int i=x;i>=1;i-=i&-i) ret+=t[i]; return ret; } int kth(int k) { int ans=0,sum=0; for(int i=log2(cnt)+1;~i;--i) { if(ans+(1<<i)<=cnt&&sum+t[ans+(1<<i)]<k) sum+=t[ans+(1<<i)], ans+=1<<i; } return ans+1; } int main() { scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d%d",&opt[i],&x[i]); if(opt[i]!=4) row[++cnt]=x[i]; } sort(row+1,row+cnt+1); cnt=unique(row+1,row+cnt+1)-row-1; for(int i=1;i<=n;++i) { if(opt[i]!=4) x[i]=lower_bound(row+1,row+1+cnt,x[i])-row; switch(opt[i]) { case 1: ins(x[i]); break; case 2: del(x[i]); break; case 3: cout<<que(x[i]-1)+1<<'\n'; break; case 4: cout<<row[kth(x[i])]<<'\n'; break; case 5: cout<<row[kth(que(x[i]-1))]<<'\n'; break; case 6: cout<<row[kth(que(x[i])+1)]<<'\n'; break; } } return 0; }
常見dfs剪枝思路:改變搜索順序(顯然)、可行性剪枝(顯然)、最優性剪枝(顯然)(左邊都是常規操做)、排除等效冗餘(不是很顯然,在寫出樸素程序後能夠考慮)、動態規劃(有點不顯然,樸素程序能夠考慮用來拍數據了)
c++
十分適用迭代加深搜索的情境:答案所在深度比較有限(條件1),搜索樹的層級規模會出現指數爆炸之類的現象(條件2)。
算法
剪枝的一個最重要的應用前提是不影響最優答案的獲取,其次是收益多少(若是剪枝所消耗的資源大於減掉的搜索子樹規模消耗的資源總和……無限遐想……)
數組
//hzwer數列動態分塊入門系列 //1 #include <bits/stdc++.h> using namespace std; const int maxn = 50001; int n, a[maxn]; int block, pos[maxn], add[maxn]; void init() { block = sqrt(n); for (int i = 1; i <= n; ++i) pos[i] = (i - 1) / block + 1; } void Add(int l, int r, int c) { if (pos[l] == pos[r]) { for (int i = l; i <= r; ++i) a[i] += c; return; } for (int i = pos[l] + 1; i <= pos[r] - 1; ++i) add[i] += c; for (int i = l; i <= pos[l] * block; ++i) a[i] += c; for (int i = (pos[r] - 1) * block + 1; i <= r; ++i) a[i] += c; } int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); init(); for (int i = 1; i <= n; ++i) { int opt, l, r, c; scanf("%d%d%d%d", &opt, &l, &r, &c); if (opt == 0) Add(l, r, c); else cout << a[r] + add[pos[r]] << '\n'; } return 0; } //2 #include<bits/stdc++.h> using namespace std; const int maxn=50005; int a[maxn], n; int b[maxn]; int add[maxn], pos[maxn], L[maxn], R[maxn]; void init() { int t=sqrt(n); int block=n/t; for(int i=1;i<=t;++i) L[i]=(i-1)*block+1,R[i]=i*block; if(R[t]<n) ++t,L[t]=R[t-1]+1,R[t]=n; for(int i=1;i<=t;++i) { for(int j=L[i];j<=R[i];++j) pos[j]=i; sort(b+L[i],b+R[i]+1); } } void Add(int l,int r,int c) { if(pos[l]==pos[r]) { for(int i=l;i<=r;++i) a[i]+=c; for(int i=L[pos[l]];i<=R[pos[l]];++i) b[i]=a[i]; sort(b+L[pos[l]],b+R[pos[l]]+1); return; } for(int i=l;i<=R[pos[l]];++i) a[i]+=c; for(int i=L[pos[r]];i<=r;++i) a[i]+=c; for(int i=L[pos[l]];i<=R[pos[l]];++i) b[i]=a[i]; for(int i=L[pos[r]];i<=R[pos[r]];++i) b[i]=a[i]; sort(b+L[pos[l]],b+R[pos[l]]+1); sort(b+L[pos[r]],b+R[pos[r]]+1); for(int i=pos[l]+1;i<=pos[r]-1;++i) add[i]+=c; } int LB(int l, int r, int tmp) { int L = l, R = r; while (L < R) { int mid = (L + R + 1) >> 1; if (b[mid] >= tmp) R = mid - 1; else L = mid; } if (b[L] >= tmp) return 0; return L - l + 1; } int Que(int l, int r, int c) { int ret = 0; if (pos[l] == pos[r]) { for (int i = l; i <= r; ++i) if (c > a[i] + add[pos[i]]) ++ret; return ret; } for (int i = l; i <= R[pos[l]]; ++i) if (c > a[i] + add[pos[i]]) ++ret; for (int i = L[pos[r]]; i <= r; ++i) if (c > a[i] + add[pos[i]]) ++ret; for (int i = pos[l] + 1; i <= pos[r] - 1; ++i) ret += LB(L[i], R[i], c - add[i]); return ret; } int main() { scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i]), b[i]=a[i]; init(); int opt,l,r,c; for(int i=1;i<=n;++i) { scanf("%d%d%d%d",&opt,&l,&r,&c); if(opt==0) Add(l,r,c); else cout<<Que(l,r,c*c)<<'\n'; } return 0; }
//k短路 #include<bits/stdc++.h> using namespace std; const int maxn=1005; const int maxm=100005; int n,m; int ct,ver[maxm],val[maxm],hed[maxm],nxt[maxm];//正圖 int uct,uver[maxm],uval[maxm],uhed[maxm],unxt[maxm];//反圖 int s,t,k; void add(int a,int b,int c) { ver[++ct]=b, val[ct]=c; nxt[ct]=hed[a],hed[a]=ct; } void uadd(int a,int b,int c) { uver[++uct]=b, uval[uct]=c; unxt[uct]=uhed[a], uhed[a]=uct; } int f[maxn], vis[maxn]; struct Heapnode{ int dist,u; }; bool operator<(Heapnode a,Heapnode b) { return !(a.dist<b.dist); } void Dij(int s) { memset(f,0x3f,sizeof f); f[s]=0; priority_queue<Heapnode>Q; Q.push((Heapnode){0,s}); while(!Q.empty()) { int u=Q.top().u; Q.pop(); if(vis[u]) continue; else vis[u]=true; for(int i=uhed[u];i;i=unxt[i]) { int v=uver[i]; if(f[v]>f[u]+uval[i]) { f[v]=f[u]+uval[i]; Q.push((Heapnode){f[v],v}); } } } } void A_star(int s) { int cnt[maxn]={0}; priority_queue<Heapnode>q; q.push((Heapnode){f[s],s}); while(!q.empty()) { int u=q.top().u, dis=q.top().dist-f[u]; q.pop(); ++cnt[u]; if(cnt[t]==k) { cout<<dis; return; } for(int i=hed[u];i;i=nxt[i]) { int v=ver[i]; q.push((Heapnode){dis+val[i]+f[v],v}); } } cout<<-1; return; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;++i) { int a,b,c; scanf("%d%d%d",&a,&b,&c); add(a,b,c); uadd(b,a,c); } scanf("%d%d%d",&s,&t,&k); if(s==t) ++k; Dij(t); A_star(s); return 0; }
既然普通BST在隨機數據下的指望樹高爲log2n(n爲節點數目),那麼爲何不給每一個節點random一個值,從而避免退化呢?
dom
若是按此作法,則本來節點的值在BST中的相對位置就不知足BST性質了,此時BST就廢了
函數
最基礎的平衡BST只須要知足兩個要求:1.知足BST性質 2.樹高不退化
優化
平衡樹的基本理論:用同一組值構造的BST不惟一
ui
單旋與雙旋是否可以保證BST的BST性質在旋轉以後依舊知足呢? 因爲雙旋操做的子操做是單旋,因此只討論單旋的BST不變性。 討論右旋的情境。 設右旋操做將節點y的左子節點x旋到y的位置上, y的右子樹爲C,x的左子樹爲A,x的右子樹爲B。 假設右旋以前,整棵樹知足BST性質。 衆所周知,BST性質被描述爲:任意節點的鍵值都大於等於其左子樹中任意節點的鍵值,且小於等於其右子樹中任意節點的鍵值。 單旋轉操做改變的是有限個節點的父子關係,可能能破壞BST性質的變化只有節點的子節點的改變。 在繞y的右旋中,子節點改變的只有三個節點: y x y的父節點fa(y) x的右子節點變爲y,顯然以x爲根的子樹知足BST性質 y的左子節點變爲B,顯然以y爲根的子樹知足BST性質 fa(y)的左子節點變爲x,顯然以fa(y)爲根的子樹知足BST性質 顯然子節點未改變的各子樹依然知足BST性質。 因此若右旋操做前BST知足BST性質,則右旋以後BST依然知足BST性質。 左旋轉操做相似。
//背板子,效果很顯著,在打代碼的同時想象旋轉操做的情境,十分有利於信道容量的拓寬(4G轉5G OwO void zig(int &p) { int q=a[p].l; a[p].l=a[q].r, a[q].r=p; p=q; } void zig(int &p) { int q=a[p].l; a[p].l=a[q].r, a[q].r=p; p=q; } void zig(int &p) { int q=a[p].l; a[p].l=a[q].r,a[q].r=p; p=q; } void zig(itn &p) { int q=a[p].l; a[p].l=a[q].r, a[q].r=p; p=q; } void zig(int &p) { int q=a[p].l; a[p].l=a[q].r, a[q].r=p; p=q; } void zig(int &p) { int q=a[p].l; a[p].l=a[q].r,a[q].r=p; p=q; } void zag(int &p) { int q=a[p].r; a[p].r=a[q].l, a[q].l=p; p=q; } void zag(int &p) { int q=a[p].r; a[p].r=a[p].l,a[q].l=p; p=q; } void zag(int &p) { int q=a[p].r; a[p].r=a[q].l,a[q].l=p; p=q; } void zag(int &p) { int q=a[p].r; q[p].r=a[q].l, a[q].l=p; p=q; } void zag(int &p) { int q=a[p].r; a[p].r=a[q].l, a[q].l=p; p=q; } void zag(int &p) { int q=a[p].r; a[p].r=a[q].l,a[q].l=p; p=q; } void zig(int &p) { int q=a[p].l; a[p].l=a[q].r, a[q].r=p; p=q; } void zag(int &p) { int q=a[p].r; a[p].r=a[q].l, a[q].l=p; p=q; }
void zig(int &p) { int q=a[p].l; a[p].l=a[q].r, a[q].r=p; p=q; } void zig(int &p) { int q=a[p].l; a[p].l=a[q].r, a[q].r=p; p=q; } void zig(int &p) { int q=a[p].l; a[p].l=a[q].r, a[q].r=p; p=q; } void zig(int &p) { int q=a[p].l; a[p].l=a[q].r, a[q].r=p; p=q; } void zig(int &p) { int q=a[p].l; a[p].l=a[q].r, a[q].r=p; p=q; } void zag(int &p) { int q=a[p].r; a[p].r=a[q].l, a[q].l=p; p=q; } void zag(int &p) { int q=a[p].r; a[p].r=a[q].l, a[q].l=p; p=q; } void zag(int &p) { int q=q[p].r; a[p].r=a[q].l, a[q].l=p; p=q; } void zag(int &p) { int q=a[p].r; a[p].r=a[q].l, a[q].l=p; p=q; } void zag(int &p) { int q=a[p].r; a[p].r=a[q].l, a[q].l=p; p=q; }
//sb散列題 char s[1000010]; unsigned long long f[1000010], p[1000010]; int main() { scanf("%s",s+1); int n=strlen(s+1), q;cin>>q; p[0]=1; for(int i=1;i<=n;++i) { f[i]=f[i-1]*131+s[i]-'a'+1; p[i]=p[i-1]*131; } for(int i=1;i<=q;++i) { int l1,r1,l2,r2; scanf("%d%d%d%d",&l1,&r1,&l2,&r2); if(f[r1]-f[l1-1]*p[r1-l1+1] == f[r2]-f[l2-1]*p[r2-l2+1]) { puts("Yes"); } else { puts("No"); } } return 0; }
通常來講作矩陣快速冪的題時只須要四個矩陣和兩個函數
spa