2022杭电多校第二场

1001 Static Query on Tree
题意:树上有A,B,C三个集合,求有多少个点在A某个点到C某个点的路径与A某个点到C某个点的路径的交上
把1到A集合中所有点的路径打上标记1,把1到B集合中所有点的路径打上标记2,把C集合所有点的子树打上标记3,答案就是三个标记都有的点的个数。然后就是用树剖线段树维护一下了,我维护了区间&和区间 | 然后查询时下放懒标记,&等于3return区间长度,| 不等于3return0,一开始只维护了区间&,T了,加上区间 | 就过了,不会算复杂度,可能复杂度是错的吧qaq,然后好像可以维护1,2,3,12,13,23,123的数量,这样查询就是O(1)了
比赛时没看到单向边,想了快一个小时没想法,浪费了好多时间,最后还是想到了做法,可惜太晚了来不及了,复杂的正解还没仔细看……
#include<iostream>
#include<vector>
#include<bitset>
using namespace std;
#define debug(x) cout<<#x<<" "<<(x)<<endl
#define lson (p<<1)
#define rson (p<<1|1)
const int maxn=2e5+10;

struct Tree
{
    int maxx[3],minn[3],flg[3];
};

int n,m[3];
vector<int> edg[maxn];
int tot=0,fa[maxn],son[maxn],siz[maxn],top[maxn],dep[maxn],dfn[maxn],rnk[maxn];
Tree tree[maxn<<2];
int a[3][maxn];

void dfs1(int fr)
{
    siz[fr]=1;
    son[fr]=-1;
    for(int to:edg[fr])
    {
        if(to==fa[fr])continue;
        dep[to]=dep[fr]+1;
        fa[to]=fr;
        dfs1(to);
        siz[fr]+=siz[to];
        if(son[fr]==-1||siz[to]>siz[son[fr]])son[fr]=to;
    }
}

void dfs2(int fr,int t)
{
    top[fr]=t;
    dfn[fr]=++tot;
    rnk[tot]=fr;
    if(son[fr]==-1)return;
    dfs2(son[fr],t);
    for(int to:edg[fr])
    {
        if(to==fa[fr]||to==son[fr])continue;
        dfs2(to,to);
    }
}

void pushup(int p)
{
    for(int i=0;i<3;++i)
    {
        tree[p].maxx[i]=tree[lson].maxx[i]|tree[rson].maxx[i];
        tree[p].minn[i]=tree[lson].minn[i]&tree[rson].minn[i];
    }
}

void pushdown(int p)
{
    for(int i=0;i<3;++i)
    {
        if(tree[p].flg[i]==0)continue;
        tree[lson].minn[i]=tree[p].flg[i]-1;
        tree[rson].minn[i]=tree[p].flg[i]-1;
        tree[lson].maxx[i]=tree[p].flg[i]-1;
        tree[rson].maxx[i]=tree[p].flg[i]-1;
        tree[lson].flg[i]=tree[p].flg[i];
        tree[rson].flg[i]=tree[p].flg[i];
        tree[p].flg[i]=0;
    }
}

void updata(int s,int t,int x,int y,int l=1,int r=n,int p=1)
{
    if(s<=l&&r<=t)
    {
        tree[p].maxx[x]=y;
        tree[p].minn[x]=y;
        tree[p].flg[x]=y+1;
        return;
    }
    if(tree[p].flg[0]||tree[p].flg[1]||tree[p].flg[2])pushdown(p);
    int mid=(l+r)>>1;
    if(s<=mid)updata(s,t,x,y,l,mid,lson);
    if(mid<t)updata(s,t,x,y,mid+1,r,rson);
    pushup(p);
}

int query(int l=1,int r=n,int p=1)
{
    if(tree[p].minn[0]&&tree[p].minn[1]&&tree[p].minn[2])return r-l+1;
    if(!tree[p].maxx[0]||!tree[p].maxx[1]||!tree[p].maxx[2])return 0;
    if(l==r)return 0;
    if(tree[p].flg[0]||tree[p].flg[1]||tree[p].flg[2])pushdown(p);
    int mid=(l+r)>>1;
    int res=0;
    res+=query(l,mid,lson);
    res+=query(mid+1,r,rson);
    return res;
}

void up(int x,int y,int z,int zz)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        updata(dfn[top[x]],dfn[x],z,zz);
        x=fa[top[x]];
    }
    if(dfn[x]<dfn[y])updata(dfn[x],dfn[y],z,zz);
    else updata(dfn[y],dfn[x],z,zz);
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int _;
    cin>>_;
    int it;
    while(_--)
    {
        for(int i=0;i<(maxn<<2);++i)
        for(int c=0;c<=2;++c)
        tree[i].maxx[c]=tree[i].minn[c]=tree[i].flg[c]=0;
        int q;
        cin>>n>>q;
        for(int i=1;i<=n;++i)
        edg[i].clear();
        for(int i=2;i<=n;++i)
        {
            cin>>it;
            edg[i].push_back(it);
            edg[it].push_back(i);
        }
        tot=0;dep[1]=1;dfs1(1);dfs2(1,1);
        // for(int i=1;i<=n;++i)
        // cout<<top[i]<<" ";cout<<endl;
        while(q--)
        {
            cin>>m[0]>>m[1]>>m[2];
            for(int c=0;c<=2;++c)
            for(int i=1;i<=m[c];++i)
            cin>>a[c][i];
            for(int c=0;c<=1;++c)
            for(int i=1;i<=m[c];++i)
            up(1,a[c][i],c,1);
            for(int i=1;i<=m[2];++i)
            updata(dfn[a[2][i]],dfn[a[2][i]]+siz[a[2][i]]-1,2,1);
            cout<<query()<<'\n';
            for(int c=0;c<=1;++c)
            for(int i=1;i<=m[c];++i)
            up(1,a[c][i],c,0);
            for(int i=1;i<=m[2];++i)
            updata(dfn[a[2][i]],dfn[a[2][i]]+siz[a[2][i]]-1,2,0);
        }
    }
    return 0;
}
1002 C++ to Python
题意:C++语句转化成py
签到题,只输出()-,数字
#include<iostream>
#include<string>
using namespace std;

string s;

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int _;
    cin>>_;
    while(_--)
    {
        cin>>s;
        for(char ch:s)
        {
            if(ch=='-'||ch==','||ch=='('||ch==')')cout<<ch;
            if(isdigit(ch))cout<<ch;
        }
        cout<<'\n';
    }
    return 0;
}
1003 Copy
题意:1操作复制l-r区间加在l-r区间后面,2操作查询第x个是多少
一次复制相当于把下面所有>r的查询减去(r-l+1),又因为l,r,x都是小于n,而答案输出的又是异或和(异或两次等于0)所以可以用bitset是维护答案。也可以把区间分为\sqrt{n}块,每次操作只会增加三块,实现时存一下块的索引和块大小的前缀和
比赛时队友想到了分块再重构的办法,可惜都不会写,赛后去要了份代码学习了一下
bitset:
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<bitset>
using namespace std;
#define debug(x) cout<<#x<<" "<<(x)<<endl
#define debug2(x,y) cout<<#x<<endl;for(int i=1;i<=y;++i)cout<<x[i]<<" ";cout<<endl
#define mem(x,y) memset(x,y,sizeof(x));
#define int long long
#define double long double
const int inf=0x3f3f3f3f3f3f3f3f;
const double eps=1e-9;
const double PI=acos(-1.0);
const int maxn=1e5+10;

struct Que
{
    int flg,l,r;
};

int n;
int a[maxn];
bitset<maxn> res;
Que que[maxn];

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // cout<<fixed<<setprecision(6);
    int _;
    cin>>_;
    while(_--)
    {
        int q;
        cin>>n>>q;
        for(int i=1;i<=n;++i)
        res[i]=0;
        for(int i=1;i<=n;++i)
        cin>>a[i];
        
        for(int i=1;i<=q;++i)
        {
            cin>>que[i].flg>>que[i].l;
            if(que[i].flg==1)cin>>que[i].r;
        }
        for(int i=q;i>=1;--i)
        {
            if(que[i].flg==1)
            {
                bitset<maxn> l=(~bitset<maxn>(0)>>(maxn-que[i].r-1))&res;
                bitset<maxn> r=(~bitset<maxn>(0)<<(que[i].r+1))&res;
                res=l^(r>>(que[i].r-que[i].l+1));
            }
            if(que[i].flg==2)
            res[que[i].l]=res[que[i].l]^1;
        }
        int ans=0;
        for(int i=1;i<=n;++i)
        if(res[i])ans^=a[i];
        cout<<ans<<'\n';
    }
    return 0;
}

分块:

#include<iostream>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
#define debug(x) cout<<#x<<" "<<(x)<<endl
#define debug2(x,y) cout<<#x<<endl;for(int i=1;i<=y;++i)cout<<x[i]<<" ";cout<<endl
#define mem(x,y) memset(x,y,sizeof(x));
#define int long long
#define double long double
const int inf=0x3f3f3f3f3f3f3f3f;
const double eps=1e-9;
const double PI=acos(-1.0);
const int maxn=2e6+10;
const int s=350;

int n;
int a[maxn];
vector<int> blk[maxn];
int sum[maxn],pos[maxn];

void solve()
{
    int q;
    cin>>n>>q;
    for(int i=1;i<=n;++i)
    cin>>a[i];
    for(int i=1;i<=n;++i)
    blk[i].clear();
    for(int i=1;i<=n;++i)
    {
        blk[(i-1)/s+1].push_back(a[i]);
        sum[(i-1)/s+1]=i;
    }
    int tot=(n-1)/s+1;
    int num=tot;
    for(int i=1;i<=tot;++i)
    pos[i]=i;
    int flg,l,r,x;
    int ans=0;
    while(q--)
    {
        cin>>flg;
        if(flg==1)
        {
            cin>>l>>r;
            int ll=lower_bound(sum+1,sum+num+1,l)-sum;
            int rr=lower_bound(sum+1,sum+num+1,r)-sum;
            l-=sum[ll-1];
            r-=sum[rr-1];
            if(ll==rr)
            {
                ++tot;
                blk[tot].clear();
                for(int i=0;i<r;++i)
                blk[tot].push_back(blk[pos[ll]][i]);
                ++tot;
                blk[tot].clear();
                for(int i=l-1;i<r;++i)
                blk[tot].push_back(blk[pos[ll]][i]);
                ++tot;
                blk[tot].clear();
                for(int i=r;i<(int)blk[pos[ll]].size();++i)
                blk[tot].push_back(blk[pos[ll]][i]);
                vector<int> t;
                t.push_back(tot-2);
                t.push_back(tot-1);
                t.push_back(tot);
                for(int i=ll+1;i<=num;++i)
                t.push_back(pos[i]);
                for(int i=0;i<(int)t.size();++i)
                {
                    pos[ll+i]=t[i];
                    sum[ll+i]=sum[ll+i-1]+blk[t[i]].size();
                    if(sum[ll+i]>=n)
                    {
                        num=ll+i;
                        break;
                    }
                }
            }
            else
            {
                ++tot;
                blk[tot].clear();
                for(int i=l-1;i<(int)blk[pos[ll]].size();++i)
                blk[tot].push_back(blk[pos[ll]][i]);
                ++tot;
                blk[tot].clear();
                for(int i=0;i<r;++i)
                blk[tot].push_back(blk[pos[rr]][i]);
                ++tot;
                blk[tot].clear();
                for(int i=r;i<(int)blk[pos[rr]].size();++i)
                blk[tot].push_back(blk[pos[rr]][i]);
                vector<int> t;
                t.push_back(tot-1);
                t.push_back(tot-2);
                for(int i=ll+1;i<rr;++i)
                t.push_back(pos[i]);
                t.push_back(tot-1);
                t.push_back(tot);
                for(int i=rr+1;i<=num;++i)
                t.push_back(pos[i]);
                for(int i=0;i<(int)t.size();++i)
                {
                    pos[rr+i]=t[i];
                    sum[rr+i]=sum[rr+i-1]+blk[t[i]].size();
                    if(sum[rr+i]>=n)
                    {
                        num=rr+i;
                        break;
                    }
                }
            }
        }
        else
        {
            cin>>x;
            int t=lower_bound(sum+1,sum+num+1,x)-sum;
            ans^=blk[pos[t]][x-sum[t-1]-1];
        }
    }
    cout<<ans<<'\n';
}

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // cout<<fixed<<setprecision(6);
    int _;
    cin>>_;
    while(_--)
    {
        solve();
    }
    return 0;
}
1004 Keychains
题面:三维的有个圆环,问是否相扣
可以求A环与B环所在的平面的交点,交点一个在B环外面,一个在B环里面就YES,这样等价于求A球于B平面交点,再等价于A球与(A平面与B平面的交线)的交点
比赛时没有继续想下去,直接开始算了,结果死于太多特判除零,赛后用向量做就好多了
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
#define double long double
const double eps=1e-9;

struct dot
{
    double x,y,z;
    dot(double xx=0,double yy=0,double zz=0):x(xx),y(yy),z(zz){}
};
inline void print(dot &a){cout<<a.x<<" "<<a.y<<" "<<a.z<<endl;}

inline dot operator+(const dot &a,const dot &b){return dot(a.x+b.x,a.y+b.y,a.z+b.z);}
inline dot operator-(const dot &a,const dot &b){return dot(a.x-b.x,a.y-b.y,a.z-b.z);}
inline double len(const dot &a){return sqrt(a.x*a.x+a.y*a.y+a.z*a.z);}
inline double operator*(const dot &a,const dot &b){return a.x*b.x+a.y*b.y+a.z*b.z;}
inline dot operator*(const double &k,const dot &a){return dot(k*a.x,k*a.y,k*a.z);}
inline dot operator/(const dot &a,const double &k){return dot(a.x/k,a.y/k,a.z/k);}
inline dot operator^(const dot &a,const dot &b){return dot(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);}
inline dot unit(const dot &a){return a/len(a);}//单位向量

struct line
{
    dot d,a,b;
    line(dot dd,dot aa):d(unit(dd)),a(aa),b(aa+unit(dd)){}
};

struct cir
{
    dot o;
    double r;
    cir(double x=0,double y=0,double z=0,double rr=0):o(dot(x,y,z)),r(rr){}
};

inline dot vert(const line &l,const dot &o)//垂足
{
    return l.a+((o-l.a)*l.d)*l.d;
}

inline double calc(double x,double y){return sqrt(x*x-y*y);}
inline vector<dot> cross_line_cir(const cir &c,const line &l)
{
    vector<dot> res;
    dot x=vert(l,c.o);
    double dd=len(x-c.o);
    if(c.r<dd-eps)return res;
    if(abs(c.r-dd)<eps)
    {
        res.push_back(x);
        return res;
    }
    double dis=calc(c.r,dd);
    res.push_back(x+dis*l.d);
    res.push_back(x-dis*l.d);
    return res;
}

inline dot intion(dot p1,dot d1,dot p2,dot d2)
{
    dot e=d1^d2;
    dot u=d1^e;
    return p1+((p2-p1)*d2)/(u*d2)*u;
}

inline bool incir(const cir &c,const dot &o){return len(o-c.o)<c.r-eps;}
inline bool outcir(const cir &c,const dot &o){return len(o-c.o)>c.r+eps;}

cir c[3];
dot f[3];

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int _;
    cin>>_;
    while(_--)
    {
        for(int i=1;i<=2;++i)
        cin>>c[i].o.x>>c[i].o.y>>c[i].o.z>>f[i].x>>f[i].y>>f[i].z>>c[i].r;
        line l(f[1]^f[2],intion(c[1].o,f[1],c[2].o,f[2]));
        // print(l.a);
        vector<dot> ans=cross_line_cir(c[1],l);
        if(ans.size()<2)
        {
            cout<<"No\n";
            continue;
        }
        // print(ans[0]);print(ans[1]);
        //if((incir(c[2],ans[0])&&outcir(c[2],ans[1]))||(outcir(c[2],ans[0])&&incir(c[2],ans[1])))
        if(incir(c[2],ans[0])^incir(c[2],ans[1]))
        cout<<"Yes\n";
        else cout<<"No\n";
    }
    return 0;
}
1007 Snatch Groceries
题意:区间相交时有多少个人
签到题,按左边界排个序即可,队友签的
#include<iostream>
#include<algorithm>
#define int long long 
using namespace std;
long long n,T,ans,now;
struct node{
    int l,r;
    bool operator<(const node&a)const{
        return l<a.l||(l==a.l&&r<a.r);
    }
}a[500000];
signed main(){
    cin>>T;
    while(T--){
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a[i].l>>a[i].r;
        }
        sort(a+1,a+1+n);
        ans=0;
        now=a[1].r;
        for(int i=2;i<=n;i++){
            if(a[i].l<=now){
                break;
            }
            now=a[i].r;
            ans++;
            if(i==n)ans++;
        }
        cout<<ans<<endl;
    }
}
1009 ShuanQ
题意:Q是P的逆元,求模数,无解就栓Q
分解一下质因数即可
比赛因为自己的问题WA好几发,哎
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<vector>
#include<set>
using namespace std;
#define debug(x) cout<<#x<<" "<<(x)<<endl
#define debug2(x,y) cout<<#x<<endl;for(int i=1;i<=y;++i)cout<<x[i]<<" ";cout<<endl
#define mem(x,y) memset(x,y,sizeof(x));
#define int long long
#define double long double
const int inf=0x3f3f3f3f3f3f3f3f;
const double eps=1e-9;
const double PI=acos(-1.0);

int p,q,x;
vector<int> d;
set<int> ans;

bool solve()
{
    d.clear();ans.clear();
    int n=p*q-1;
    for(int i=2;i*i<=n;++i)
    {
        if(n%i==0)
        {
            d.push_back(i);
            while(n%i==0)n/=i;
        }
    }
    if(n>1)d.push_back(n);
    for(int it:d)
    {
        if(it>p&&it>q&&it>x&&p*q%it==1)
        ans.insert(x*q%it);
    }
    if(ans.size()==1)return 1;
    else return 0;
}

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // cout<<fixed<<setprecision(6);
    int _;
    cin>>_;
    while(_--)
    {
        cin>>p>>q>>x;
        if(solve())cout<<*ans.begin()<<'\n';
        else cout<<"shuanQ\n";
    }
    return 0;
}
1011 DOS Card
题意:在l-r的区间里选四个数,组成两对,每次的答案是ai*ai-aj*aj(i<j),求最大
线段树维护一些信息,细节看代码
线段树永远想不到维护什么……
题解做法:
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define debug(x) cout<<#x<<" "<<(x)<<endl
#define debug2(x,y) cout<<#x<<endl;for(int i=1;i<=y;++i)cout<<x[i]<<" ";cout<<endl
#define mem(x,y) memset(x,y,sizeof(x));
#define int long long
#define double long double
#define lson (p<<1)
#define rson (p<<1|1)
const int inf=0x3f3f3f3f3f3f3f;
const double eps=1e-9;
const double PI=acos(-1.0);
const int maxn=2e5+10;

struct Node
{
    int len;
    int max1,max2,min1,min2,d1,d2,d1_min,d1_max;
    void init()
    {
        max1=max2=d1=d2=d1_min=d1_max=-inf;
        min1=min2=inf;
    }
    void up_max(int x)
    {
        if(x>max1)max2=max1,max1=x;
        else if(x>max2)max2=x;
    }
    void up_min(int x)
    {
        if(x<min1)min2=min1,min1=x;
        else if(x<min2)min2=x;
    }
    Node operator+(const Node &r)const
    {
        Node res;
        res.len=len+r.len;
        res.init();
        res.up_max(max1);res.up_max(max2);
        res.up_max(r.max1);res.up_max(r.max2);
        res.up_min(min1);res.up_min(min2);
        res.up_min(r.min1);res.up_min(r.min2);

        res.d1=max({d1,r.d1,max1-r.min1});
        res.d2=max({d2,r.d2,max1+max2-r.min1-r.min2,d1_max-r.min1,max1+r.d1_min,d1+r.d1});
        res.d1_max=max({d1_max,r.d1_max,d1+r.max1,max1+r.d1});
        res.d1_max=max(res.d1_max,max1+max2-r.min1);
        res.d1_max=max(res.d1_max,max1+r.max1-r.min1);
        res.d1_min=max({d1_min,r.d1_min,d1-r.min1,-min1+r.d1});
        res.d1_min=max(res.d1_min,max1-r.min1-r.min2);
        res.d1_min=max(res.d1_min,max1-min1-r.min1);
        return res;
    }
};

int n;
int a[maxn];
Node tree[maxn<<2];

void build(int l=1,int r=n,int p=1)
{
    tree[p].init();
    if(l==r)
    {
        tree[p].len=1;
        tree[p].up_min(a[l]*a[l]);
        tree[p].up_max(a[l]*a[l]);
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,lson);
    build(mid+1,r,rson);
    tree[p]=tree[lson]+tree[rson];
}

Node query(int s,int t,int l=1,int r=n,int p=1)
{
    // cout<<l<<r<<" "<<p<<endl;
    if(s<=l&&r<=t)return tree[p];
    int mid=(l+r)>>1;
    if(t<=mid)return query(s,t,l,mid,lson);
    else if(mid<s)return query(s,t,mid+1,r,rson);
    else 
    {
        Node it=query(s,t,l,mid,lson)+query(s,t,mid+1,r,rson);
        return it;
    }
}

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // cout<<fixed<<setprecision(6);
    int _;
    cin>>_;
    while(_--)
    {
        int q;
        cin>>n>>q;
        for(int i=1;i<=n;++i)
        cin>>a[i];
        build();
        int l,r;
        while(q--)
        {
            cin>>l>>r;
            Node ans=query(l,r);
            cout<<ans.d2<<'\n';
        }
    }
    return 0;
}

神奇的变量名做法:

#include<iostream>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define debug(x) cout<<#x<<" "<<(x)<<endl
#define debug2(x,y) cout<<#x<<endl;for(int i=1;i<=y;++i)cout<<x[i]<<" ";cout<<endl
#define mem(x,y) memset(x,y,sizeof(x));
#define int long long
#define double long double
#define lson (p<<1)
#define rson (p<<1|1)
const int inf=0x3f3f3f3f3f3f3f3f;
const double eps=1e-9;
const double PI=acos(-1.0);
const int maxn=2e5+10;

struct Node
{
    int d,x,xx,dd,dx,xd,dxd,xdx,ddx,dxx,dxdx,ddxx;
    void init()
    {
        d=x=xx=dd=dx=xd=dxd=xdx=ddx=dxx=dxdx=ddxx=-inf;
    }
    Node operator+(const Node &r)const
    {
        Node res;
        res.init();
        res.d=max(d,r.d);
        res.x=max(x,r.x);
        res.xx=max({xx,r.xx,x+r.x});
        res.dd=max({dd,r.dd,d+r.d});
        res.xd=max({xd,r.xd,x+r.d});
        res.dx=max({dx,r.dx,d+r.x});
        res.ddx=max({ddx,r.ddx,dd+r.x,d+r.dx});
        res.dxd=max({dxd,r.dxd,dx+r.d,d+r.xd});
        res.dxx=max({dxx,r.dxx,d+r.xx,dx+r.x});
        res.xdx=max({xdx,r.xdx,x+r.dx,xd+r.x});
        res.ddxx=max({ddxx,r.ddxx,d+r.dxx,dd+r.xx,ddx+r.x});
        res.dxdx=max({dxdx,r.dxdx,d+r.xdx,dx+r.dx,dxd+r.x});
        return res;
    }
};

int n;
int a[maxn];
Node tree[maxn<<2];

void build(int l=1,int r=n,int p=1)
{
    tree[p].init();
    if(l==r)
    {
        tree[p].x=-a[l]*a[l];
        tree[p].d=a[l]*a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,lson);
    build(mid+1,r,rson);
    tree[p]=tree[lson]+tree[rson];
}

Node query(int s,int t,int l=1,int r=n,int p=1)
{
    if(s<=l&&r<=t)return tree[p];
    int mid=(l+r)>>1;
    if(t<=mid)return query(s,t,l,mid,lson);
    else if(mid<s)return query(s,t,mid+1,r,rson);
    else return query(s,t,l,mid,lson)+query(s,t,mid+1,r,rson);
}

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // cout<<fixed<<setprecision(6);
    int _;
    cin>>_;
    while(_--)
    {
        int q;
        cin>>n>>q;
        for(int i=1;i<=n;++i)
        cin>>a[i];
        build();
        int l,r;
        while(q--)
        {
            cin>>l>>r;
            Node ans=query(l,r);
            cout<<max(ans.ddxx,ans.dxdx)<<endl;
        }
    }
    return 0;
}
1012 Luxury cruise ship
题意:每天加7或31或365,正好存x最少需要多少天
bfs预处理到lca(7,31,365),一个轮回,答案是x/79205*(7*31)+ans[x%79205],好像也可以背包……
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
#define debug(x) cout<<#x<<" "<<(x)<<endl
#define debug2(x,y) cout<<#x<<endl;for(int i=1;i<=y;++i)cout<<x[i]<<" ";cout<<endl
#define mem(x,y) memset(x,y,sizeof(x));
#define int long long
#define double long double
const int inf=0x3f3f3f3f3f3f3f3f;
const double eps=1e-9;
const double PI=acos(-1.0);
const int maxn=79205+10;

struct Node
{
    int res,cnt;
};

int n;
bool vis[maxn];
int ans[maxn];

void init()
{
    mem(vis,0);
    mem(ans,-1);
    queue<Node> q;
    q.push({0,0});
    while(!q.empty())
    {
        Node cur=q.front();
        q.pop();
        if(vis[cur.res])continue;
        vis[cur.res]=1;
        ans[cur.res]=cur.cnt;
        if(cur.res+7<=79205)q.push({cur.res+7,cur.cnt+1});
        if(cur.res+31<=79205)q.push({cur.res+31,cur.cnt+1});
        if(cur.res+365<=79205)q.push({cur.res+365,cur.cnt+1});
    }
}

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // cout<<fixed<<setprecision(6);
    init();
    int _;
    cin>>_;
    while(_--)
    {
        cin>>n;
        if(ans[n%79205]!=-1)cout<<n/79205*(7*31)+ans[n%79205]<<'\n';
        else cout<<-1<<'\n';
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值