点分治 模板题

在这里插入图片描述
就明白了个模板题,先放个模板。
多做一些题后在来整理下。

#pragma GCC optimize(3,"Ofast","inline")  	//G++
#include<bits/stdc++.h>
#define mem(a,x) memset(a,x,sizeof(a))
#define debug(x) cout << #x << ": " << x << endl;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fcout cout<<setprecision(4)<<fixed
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;

const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const int maxn = 1e4+5;

template<typename T> void read(T &x){
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args) {
    read(first);
    read(args...);
}
vector<pii>edge[maxn];
int siz[maxn],maxp[maxn],q[105],dis[maxn],tmp[maxn];
int Rsum,rt,cnt,n,m;
bool ans[maxn],vis[maxn],judge[10000005];
void addedge(int x,int y,int w){
    edge[x].push_back({y,w});
    edge[y].push_back({x,w});
}
void getroot(int u,int fa){
    siz[u]=1,maxp[u]=0;
    for(auto it:edge[u]){
        int v=it.first;
        if(v==fa||vis[v]) continue ;
        getroot(v,u);
        siz[u]+=siz[v];
        maxp[u]=max(maxp[u],siz[v]);
    }
    maxp[u]=max(maxp[u],Rsum-siz[u]);
    if(maxp[u]<maxp[rt]) rt=u;
}
void getdis(int u,int fa){
    if(dis[u]<10000001)
         tmp[++cnt]=dis[u];
    for(auto it:edge[u]){
        int v=it.first,w=it.second;
        if(v==fa||vis[v]) continue;
        dis[v]=dis[u]+w;
        getdis(v,u);
    }
}
void solve(int u){
    queue<int>que;
    for(auto it:edge[u]){
        int v=it.first;
        if(vis[v]) continue;
        cnt=0;
        dis[v]=it.second;
        getdis(v,u);
        for(int i=1;i<=cnt;i++){
            for(int j=1;j<=m;j++){
                if(q[j]>=tmp[i])
                    ans[j]|=judge[q[j]-tmp[i]];
            }
        }
        for(int i=1;i<=cnt;i++){
            judge[tmp[i]]=1;
            que.push(tmp[i]);
        }
    }
    while(que.size()){
        judge[que.front()]=0;
        que.pop();
    }
}
void divide(int u){
    judge[0]=vis[u]=true;
    solve(u);
    for(auto it:edge[u]){
        int v=it.first;
        if(vis[v]) continue;
        maxp[rt=0]=Rsum=siz[v];
        getroot(v,0);
        getroot(rt,0);
        divide(rt);
    }
}
int main()
{
    read(n,m);
    for(int i=1,u,v,w;i<=n-1;i++){
        read(u,v,w);
        addedge(u,v,w);
    }
    for(int i=1;i<=m;i++) read(q[i]);
    maxp[rt=0]=Rsum=n;
    getroot(1,0);
    getroot(rt,0);
    divide(rt);
    for(int i=1;i<=m;i++){
        puts(ans[i]?"AYE":"NAY");
    }
}

在这里插入图片描述
多了个树状数组维护

#pragma GCC optimize(3,"Ofast","inline")  	//G++
#include<bits/stdc++.h>
#define mem(a,x) memset(a,x,sizeof(a))
#define debug(x) cout << #x << ": " << x << endl;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fcout cout<<setprecision(8)<<fixed
using namespace std;
//======================================
namespace FastIO {char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh1 = '\n', hh2 = ' ';int p, p3 = -1;
void read() {}
void print() {buf2[p3] = hh1;}
inline int getc() {return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;}
inline void flush() {fwrite(buf2, 1, p3 + 1, stdout), p3 = -1;}
template <typename T, typename... T2>
inline void read(T &x, T2 &... oth) {int f = 0;x = 0;char ch = getc();while (!isdigit(ch)) {if (ch == '-')f = 1;ch = getc();}while (isdigit(ch)) {x = x * 10 + ch - 48;ch = getc();}x = f ? -x : x;read(oth...);}
template <typename T, typename... T2>
inline void print(T x, T2... oth) {if (p3 > 1 << 20)flush();if (x < 0)buf2[++p3] = 45, x = -x;do {a[++p] = x % 10 + 48;} while (x /= 10);do {buf2[++p3] = a[p];} while (--p);buf2[++p3] = hh2;print(oth...);}} // namespace FastIO
using FastIO::print;
using FastIO::read;
typedef long long ll;
typedef pair<int,int> pii;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const int maxn = 1e4+5;
//======================================
vector<pii>edge[maxn];
int sum[maxn*1000],siz[maxn],maxp[maxn],dis[maxn],tmp[maxn];
int rt,n,m,N=10000001,Rsum,cnt,ans;
bool vis[maxn];
void _add(int p,int x){
    while(p<=N) sum[p]+=x,p+=p&-p;
}
void add(int l,int x){
    ++l;
    _add(l,x),_add(N+2,-x);
}
int ask(int p){
    ++p;
    int res=0;
    while(p) res+=sum[p],p-=p&-p;
    return res;
}
void addedge(int x,int y,int w){
    edge[x].push_back({y,w});
}
void getrt(int u,int fa){
    siz[u]=1,maxp[u]=0;
    for(auto it:edge[u]){
        int v=it.first;
        if(v==fa||vis[v]) continue;
        getrt(v,u);
        siz[u]+=siz[v];
        maxp[u]=max(maxp[u],siz[v]);
    }
    maxp[u]=max(maxp[u],Rsum-siz[u]);
    if(maxp[u]<maxp[rt]) rt=u;
}
void getdis(int u,int fa){
    tmp[++cnt]=dis[u];
    for(auto it:edge[u]){
        int v=it.first,w=it.second;
        if(v==fa||vis[v]) continue;
        dis[v]=dis[u]+w;
        getdis(v,u);
    }
}
void solve(int u){
    queue<int>que;
    for(auto it:edge[u]){
        int v=it.first,w=it.second;
        if(vis[v]) continue;
        dis[v]=w,cnt=0;
        getdis(v,u);
        for(int i=1;i<=cnt;i++){
            if(tmp[i]>m) continue;
            ans++;
            ans+=ask(m-tmp[i]);
        }
        for(int i=1;i<=cnt;i++){
            add(tmp[i],1);
            que.push(tmp[i]);
        }
    }
    while(que.size()){
        add(que.front(),-1);
        que.pop();
    }
}
void divide(int u){
    vis[u]=1;
    solve(u);
    for(auto it:edge[u]){
        int v=it.first;
        if(vis[v]) continue;
        maxp[rt=0]=Rsum=siz[v];
        getrt(v,0);
        getrt(rt,0);
        divide(rt);
    }
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    clock_t c1 = clock();
#endif
//**************************************
    while(cin>>n>>m&&(n|m)){
        ans=0;
        for(int i=1,x,y,w;i<=n-1;i++) {
            cin>>x>>y>>w;
            x++,y++;
            addedge(x,y,w);
            addedge(y,x,w);
        }
        maxp[rt=0]=Rsum=n;
        getrt(1,0);
        getrt(rt,0);
        divide(rt);
        cout<<ans<<"\n";
        for(int i=1;i<=n;i++){
            edge[i].clear();
            vis[i]=0;
        }
    }
//**************************************
  //  FastIO::flush();
#ifndef ONLINE_JUDGE
    cerr << "Time:" << clock() - c1 << "ms" << endl;
#endif
    return 0;
}
/*
 * ┌───┐   ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐
 * │Esc│   │ F1│ F2│ F3│ F4│ │ F5│ F6│ F7│ F8│ │ F9│F10│F11│F12│ │P/S│S L│P/B│  ┌┐    ┌┐    ┌┐
 * └───┘   └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘  └┘    └┘    └┘
 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ ┌───┬───┬───┐ ┌───┬───┬───┬───┐
 *~ `│! 1│@ 2│# 3│$ 4% 5^ 6& 7* 8( 9) 0│_ -+ =│ BacSp │ │Ins│Hom│PUp│ │Num│ /*-* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ ├───┼───┼───┤ ├───┼───┼───┼───┤
 * │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{ [} ]| \ │ │Del│End│PDn│ │ 789 │   │
 * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ └───┴───┴───┘ ├───┼───┼───┤ +* │ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│" '│ Enter  │               │ 456 │   │
 * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤     ┌───┐     ├───┼───┼───┼───┤
 * │ Shift  │ Z │ X │ C │ V │ B │ N │ M │< ,> .? /│  Shift   │     │ ↑ │     │ 123 │   │
 * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││
 * │ Ctrl│ Win│ Alt│         Space         │ Alt│ Win│Menu│Ctrl│ │ ← │ ↓ │ → │ │   0. │←─┘│
 * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘
 */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值