NOIP2019翻車前寫(and 抄)過的代碼

咕咕咕。按上傳時間升序排列。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

相關文章
相關標籤/搜索