咕咕咕。按上传时间升序排列。
//树的重心
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)
",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
",++T);
if(solve()==-1) printf("Impossible.
");
else
out(),printf("
");
}
}
//食物鏈
#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]<<'
';
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
",++id);
int ans=solve();
if(ans<0) printf("Bugs cannot be fixed.
");
else printf("Fastest sequence takes %d seconds.
",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
");
else
printf("%lld
",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)<<'
';
}
}
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<<'
';
break;
case 4:
cout<<row[kth(x[i])]<<'
';
break;
case 5:
cout<<row[kth(que(x[i]-1))]<<'
';
break;
case 6:
cout<<row[kth(que(x[i])+1)]<<'
';
break;
}
}
return 0;
}
常见dfs剪枝思路:改变搜索顺序(显然)、可行性剪枝(显然)、最优性剪枝(显然)(左边都是常规操作)、排除等效冗余(不是很显然,在写出朴素程序后可以考虑)、动态规划(有点不显然,朴素程序可以考虑用来拍数据了)
十分适用迭代加深搜索的情境:答案所在深度比较有限(条件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]] << '
';
}
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)<<'
';
}
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一个值,从而避免退化呢?
如果按此做法,则原本节点的值在BST中的相对位置就不满足BST性质了,此时BST就废了
最基础的平衡BST只需要满足两个要求:1.满足BST性质 2.树高不退化
平衡树的基本理论:用同一组值构造的BST不唯一
单旋与双旋是否能够保证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;
}
一般来说做矩阵快速幂的题时只需要四个矩阵和两个函数