noip近五年复习

一.noip2018

day 1

T1 铺设道路

13,18年通用入门题

#define ll long long
int n,a[100006];
int main()
{
    //freopen("in.txt","r",stdin);
    rd(n);
    int ans=0;
    inc(i,1,n)
    {
        rd(a[i]);
        if(a[i]>a[i-1])ans+=(a[i]-a[i-1]);
    }
    
    printf("%d",ans);
    re 0;
}
View Code

当时我还写了好久,用了一种极其怪力的方法a了ta

 

T2 货币系统

完全背包嘛

int n,a[100],vis[30000];
int main()
{
    //freopen("in.txt","r",stdin);
    int T;
    rd(T);
    while(T--)
    {
        rd(n);
        inc(i,1,n)rd(a[i]);
        memset(vis,0,sizeof vis);
        vis[0]=1;
        int ans=0;
        sort(a+1,a+n+1);
        inc(i,1,n)
        {
            if(!vis[a[i]])++ans;
            //vis[a[i]]=1;
            inc(j,a[i],a[n])
            vis[j]|=vis[j-a[i]];
        }
        printf("%d\n",ans);
    }
    re 0;
}
View Code

想当年,我可是全凭这道题爆搜的70pts,压线2=

(说来惭愧……)

 

T3 塞道修建

这题思想还是较为简单,

二分一下答案,在判断能否

对于每个点将所有能配对的或自成一队的路径全部弄好

将剩下中最长的路径返回参与父节点选拔

就是stl用得伤心(因为要维护删除,所以迭代器随时要更新)

/*
user liangsiyi.
language: c++
*/
#include<bits/stdc++.h>
#define re return
#define st static
#define Min(a,b) (a)>(b)?(b):(a)
#define Max(a,b) (a)>(b)?(a):(b)
#define mem(a,x) memset(a,x,sizeof(a))
#define inc(i,l,r) for(register int i=l;i<=r;++i)
#define dec(i,l,r) for(register int i=r;i>=l;--i)
const int M=50000+5;
using namespace std;
int n,m,k,mid,flag=1,head[M],f[M],ff[M],s[M];
template <typename T>inline void read(T &x)
{
    bool f=0;char c;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    x=f==1?-x:x;
}
template <typename T>void put(const T x)
{
    if(x>9)put(x/10);
    putchar((x%10)|48);
}
template<typename T>inline void write(const T x)
{
    if(x<0)putchar('-'),put(-x);
    else put(x);
}
struct node
{
    int to,nt,v;
}e[M<<1];

void add(int x,int y,int z)
{
    e[++k].to=y;e[k].v=z;e[k].nt=head[x];head[x]=k;
    e[++k].to=x;e[k].v=z;e[k].nt=head[y];head[y]=k;
}

void dfs(int u,int fa)
{
    f[u]=ff[u]=0;
    multiset<int>vi;
    for(int i=head[u];i;i=e[i].nt)
    {
        int v=e[i].to,w=e[i].v;
        if(v==fa)continue;
        dfs(v,u);                //可能会重复dfs(同一v)但u不同 ,结果不同 
        f[u]+=f[v];
        if(ff[v]+w>=mid)f[u]++;
        else vi.insert(ff[v]+w);
    }    
    while(!vi.empty())
    {
        multiset<int>::iterator i=vi.begin();
        int x=*i;vi.erase(i);
        multiset<int>::iterator y=vi.lower_bound(mid-x);
        if(y==vi.end())ff[u]=x;
        else {
            f[u]++;
            vi.erase(y);    
        }
    }
}

bool check()
{    
    dfs(1,0);
    if(f[1]>=m)re 1;
    re 0;
    
}
bool check1()
{

    f[1]=0;
    int l=1;
    dec(i,l,n-1)
    if(s[i]>=mid)f[1]++;
    else {
        while(s[i]+s[l]<mid&&l<i)l++;
        if(s[i]+s[l]>=mid&&l<i)f[1]++,l++;
        else break;
    }
    if(f[1]>=m)re 1;
    re 0;
    
}

int main()
{
    
    int x,y,z,l=1e6,r=0;
    read(n);read(m);
    inc(i,1,n-1){
        read(x);read(y);read(z);
        add(x,y,z);    
        l=Min(l,z);r+=z;
        if(x!=1)flag=0;s[i]=z;
    }
    sort(s+1,s+n);
    
    if(flag)
    {
        while(l<=r)
        {
        mid=(l+r)>>1;
        if(check1())l=mid+1;
        else r=mid-1;
        }
    }
    else while(l<=r)
    {
        mid=(l+r)>>1;
        if(check())l=mid+1;
        else r=mid-1;
    }
    printf("%d",l-1);
    re 0;
}
View Code

 

day 2

T1 旅行

基环树拆点

发现基环树要么最大独立子集(强制枚举选与不选)

要么在环上区间dp

此题很显然,很暴力(毕竟是T1)

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i) 
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

const int maxn=5005;
int n,m,hd[maxn];
struct node{
    int to,nt;
}e[maxn<<1];
int k=1;
inline void add(int x,int y){
    e[++k]=(node){y,hd[x]};hd[x]=k; 
}


namespace SOLU1{
    
    inline void dfs(int x,int fa)
    {
        printf("%d ",x);
        priority_queue<int,vector<int>,greater<int> >q;
        for(int i=hd[x];i;i=e[i].nt){
            int v=e[i].to;
            if(v!=fa)q.push(v);
        }
        while(!q.empty())
        {
            int v=q.top();q.pop();
            dfs(v,x);
        }
    }
    
}

namespace SOLU2{
    int bridge[maxn<<1],ban[maxn<<1],dfn[maxn],low[maxn],tot;
    inline void tarjan(int x,int E)
    {
        dfn[x]=low[x]=++tot;
        for(int i=hd[x];i;i=e[i].nt)
        {
            int v=e[i].to;
            if(i!=(E^1))
            {
                if(!dfn[v])
                {
                    tarjan(v,i);
                    if(low[v]>dfn[x])bridge[i]=bridge[i^1]=1;
                    else low[x]=min(low[x],low[v]);
                }
                else low[x]=min(low[x],dfn[v]);
            }
        }
    }
    
    int a[maxn],b[maxn],tot_a,flag;
    inline bool dfs(int x,int fa)
    {
        a[++tot_a]=x;
        if(x>b[tot_a]&&(!flag))re 0;
        else if(x<b[tot_a])flag=1;
        priority_queue<int,vector<int>,greater<int> >q;
        for(int i=hd[x];i;i=e[i].nt)
        {
            int v=e[i].to;
            if(v==fa||ban[i])continue;
            q.push(v);
        }
        while(!q.empty())
        {
            int v=q.top();q.pop();
            if(!dfs(v,x))re 0;
        }
        re 1;
    }
    
    inline void work()
    {
        inc(i,1,n)if(!dfn[i])tarjan(i,0);    
        inc(i,1,n)b[i]=n+1;
        
        for(int i=2;i<=k;i+=2)
        if(!bridge[i])
        {
            ban[i]=ban[i^1]=1;
            tot_a=0;flag=0;
            if(dfs(1,0))
            {
                inc(i,1,n)b[i]=a[i];
            }
            ban[i]=ban[i^1]=0;
        }
        inc(i,1,n)
        printf("%d ",b[i]);
    }
}

int main()
{
    freopen("in.txt","r",stdin);
    int x,y;
    rd(n),rd(m);
    inc(i,1,m)
    {
        rd(x),rd(y);
        add(x,y);
        add(y,x);
    }
    
    if(m==n-1)SOLU1::dfs(1,0);
    else SOLU2::work();
    re 0;
} 
View Code

 

T2 填数游戏

骗分过样例,打表出奇迹

这道题是真~打表找规律的好题

反正我今天只凹了65pts

剩下的只要是不会暴力,不过在考场上要真的不会,最好还是弄一下这种题

规律笔记比较好找

int main()
{
    rd(n),rd(m);
    if(n>m)swap(n,m);
    if(n==1)
    {
        printf("%lld",Pow(2ll,m));    
        re 0;
    }
    if(n<=3&&m<=3)
    {
        if(n==2){
            if(m==2)printf("12");
            else if(m==3)printf("36");
        }
        else printf("112"); 
        re 0;
    }
    if(n==2)
    {
        int now=m-1;
        printf("%lld",Pow(3,now)*4%P);
    }
    else if(n==3)
    {
        int now=m-3;
        printf("%lld",Pow(3,now)*112%P);
    }
    else{
        if(m == n)printf("%lld",(83*Pow(8,n)%P+5*Pow(2,n+7)%P)*190104168%P);
        else printf("%lld",(83*Pow(8,n)%P+Pow(2,n+8))*Pow(3,m-n-1)%P*570312504%P);
    }
    re 0;
} 
View Code

 

T3 保卫王国

ddp板子题

毒瘤吧,wc才讲就考到noip中来

只能暴力44pts(最大独立子集)

A:44:

const int maxn=2005;
#define ll long long
int n,m,p[maxn],hd[maxn];
ll f[maxn][2],inf=999999999999;
struct node{
    int to,nt;
}e[maxn<<1];

int k;
inline void add(int x,int y){
    e[++k]=(node){y,hd[x]};hd[x]=k;
}

int limit[maxn];
inline void dfs(int x,int fa){
    f[x][1]=p[x];
    f[x][0]=0;
    for(int i=hd[x];i;i=e[i].nt)     
    {
        int v=e[i].to;
        if(v==fa)continue;
        dfs(v,x);
        f[x][0]+=f[v][1];
        f[x][1]+=min(f[v][1],f[v][0]);
    }
    if(~limit[x])f[x][limit[x]]=inf;
}
int main()
{
    freopen("in.txt","r",stdin);
    rd(n),rd(m);
    char GT[45];
    memset(limit,-1,sizeof limit);
    scanf("%s",GT);
    inc(i,1,n)rd(p[i]);
    int x,y,a,b;
    inc(i,2,n)
    {
        rd(x),rd(y);
        add(x,y),add(y,x);
    }
    inc(i,1,m)
    {
        rd(x),rd(a),rd(y);rd(b);
        limit[x]=a^1;
        limit[y]=b^1;
        dfs(1,0);
        ll ans=min(f[1][0],f[1][1]);
        if(ans>=inf)puts("-1");
        else printf("%lld\n",ans);
        limit[x]=-1;
        limit[y]=-1;
    } 
    re 0;
} 
View Code

B:100

维护了一个直达链根的bot,树剖,寻常dp一下

在建线段树的时候以重儿子为转移矩阵核心(分为重儿子与其他儿子两类),

弄出一个关于矩阵的东西,加速和维护转移

      ret.s[0][0]=min(s[0][0]+a.s[0][0],s[0][1]+a.s[1][0]); 
        ret.s[0][1]=min(s[0][0]+a.s[0][1],s[0][1]+a.s[1][1]); 
        ret.s[1][0]=min(s[1][0]+a.s[0][0],s[1][1]+a.s[1][0]); 
        ret.s[1][1]=min(s[1][0]+a.s[0][1],s[1][1]+a.s[1][1]); 

大概就是这个东西

单点修改,再修改回来

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i) 
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

#define int long long
const int maxn=1e5+5;
int n,m,hd[maxn],p[maxn];
struct node{
    int to,nt;
}e[maxn<<1];
int k;
inline void add(int x,int y)
{
    e[++k].to=y;e[k].nt=hd[x];hd[x]=k;
    e[++k].to=x;e[k].nt=hd[y];hd[y]=k;
}

int siz[maxn],son[maxn],fa[maxn];
inline void dfs1(int x)
{
    siz[x]=1;
    for(int i=hd[x];i;i=e[i].nt)
    {
        int v=e[i].to;if(v==fa[x])continue;
        fa[v]=x;dfs1(v);
        siz[x]+=siz[v];
        if(siz[v]>siz[son[x]])son[x]=v;
    }
}
int tot,seg[maxn],rev[maxn],top[maxn],bot[maxn];
inline void dfs2(int x,int fp)
{
    seg[x]=++tot;rev[tot]=x;
    top[x]=fp; 
    if(son[x])
    {
        dfs2(son[x],fp);bot[x]=bot[son[x]];
        for(int i=hd[x];i;i=e[i].nt)
            if(!top[e[i].to])dfs2(e[i].to,e[i].to);
    }
    else bot[x]=x;
}
int f[maxn][2];
inline void dp(int x)
{
    f[x][1]=p[x],f[x][0]=0;
    for(int i=hd[x];i;i=e[i].nt)
    {
        int v=e[i].to;
        if(e[i].to==fa[x])continue;
        dp(v);
        f[x][1]+=min(f[v][0],f[v][1]);
        f[x][0]+=f[v][1];
    }
}

//-------------------------
struct Matrix{
    int s[2][2];
    inline Matrix operator*(Matrix a)const 
    {
        Matrix ret;
        ret.s[0][0]=min(s[0][0]+a.s[0][0],s[0][1]+a.s[1][0]); 
        ret.s[0][1]=min(s[0][0]+a.s[0][1],s[0][1]+a.s[1][1]); 
        ret.s[1][0]=min(s[1][0]+a.s[0][0],s[1][1]+a.s[1][0]); 
        ret.s[1][1]=min(s[1][0]+a.s[0][1],s[1][1]+a.s[1][1]); 
        re ret;
    }
}t[maxn<<2],tmp[maxn],be[maxn];
const int inf=2147483647;
#define ls rt<<1
#define rs rt<<1|1
inline void build(int rt,int l,int r)
{
    if(l==r)
    {
        int x=rev[l];
        int g1=f[x][1]-min(f[son[x]][0],f[son[x]][1]),g0=f[x][0]-f[son[x]][1];
        be[l]=tmp[l]=t[rt]=(Matrix){g1,g1,g0,inf};
        re ;
    }
    
    int mid=(l+r)>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    t[rt]=t[ls]*t[rs];
}

inline Matrix query(int rt,int l,int r,int x,int y)
{
    if(x<=l&&r<=y)
        re t[rt];
    int mid=(l+r)>>1;
    if(y<=mid)re query(ls,l,mid,x,y);
    else if(x>mid) re query(rs,mid+1,r,x,y);
    re query(ls,l,mid,x,y)*query(rs,mid+1,r,x,y);
}

inline void Modify(int rt,int l,int r,int pos)
{
    if(l==r)
    {
        t[rt]=tmp[l];
        re ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)Modify(ls,l,mid,pos);
    else Modify(rs,mid+1,r,pos);
    t[rt]=t[ls]*t[rs];
}

inline Matrix Get_mat(int x){re query(1,1,n,seg[top[x]],seg[bot[x]]);}

inline void modify(int x,int y)
{
    if(y)tmp[seg[x]].s[0][0]=tmp[seg[x]].s[0][1]=inf;
    else tmp[seg[x]].s[1][0]=inf;
    while(x)
    {
        Matrix a=Get_mat(x);Modify(1,1,n,seg[x]);
        Matrix b=Get_mat(x);
        x=fa[top[x]];
        if(!x)re ;
         tmp[seg[x]].s[0][1]=(tmp[seg[x]].s[0][0]+=min(b.s[1][0],b.s[0][0])-min(a.s[1][0],a.s[0][0]));
         tmp[seg[x]].s[1][0]+=b.s[0][0]-a.s[0][0];
    }
}

inline void rebuild(int x)
{
    while(x)
    {
        tmp[seg[x]]=be[seg[x]];
        Modify(1,1,n,seg[x]);
        x=fa[top[x]];
    }
}
#undef int
int main()
{
    #define int long long
//    freopen("in.txt","r",stdin);
    int x,y;
    char TY[4];
    rd(n),rd(m);
    scanf("%s",TY);
    inc(i,1,n)rd(p[i]);
    inc(i,2,n)
    {
        rd(x),rd(y);
        add(x,y);
    }
    dfs1(1);dfs2(1,1);dp(1);build(1,1,n);
    
    int a,b;
    inc(i,1,m)
    {
        rd(a),rd(x),rd(b),rd(y);
        x^=1;y^=1;
        if(x&&y&&(fa[a]==b||fa[b]==a))puts("-1");
        else
        {
            modify(a,x);modify(b,y);
            Matrix ans=Get_mat(1);
            int now=min(ans.s[1][0],ans.s[0][0]);
            printf("%lld\n",now); 
            rebuild(a);rebuild(b);        
        }
    }
    re 0;
} 
View Code

简而言之,就是通过树链剖分弄成线段树,使用矩阵(及区间可加性)加速

 

 

二.noip2017

day 1

T1 小凯的诱惑

这打表,这规律找得

我有50%是找不到这规律的

#include<bits/stdc++.h>
using namespace std;
int main()
{
    long long a,b;
    scanf("%lld%lld",&a,&b);
    printf("%lld",a*b-(a+b));
    return 0;
} 
View Code

 

T2 时间复杂度 

 蓝题的模拟 可见这题有多恶心了

 

#include<bits/stdc++.h>
#define re return 
#define st static
#define mem(a,b) memset((a),(b),sizeof(a))
#define Min(a,b) (a)<(b)?(a):(b)
#define MAx(a,b) (a)>(b)?(a):(b)
#define inc(i,l,r) for(int i=l;i<=r;++i)
#define dec(i,l,r) for(int i=l;i>=r;--i)

using namespace std;
int z,n,t,w,vis[100],ins[100];
string code[105],o;
char c[105];

int gm(int i)
{
    if(code[i][z+1]=='n'){
        ++z;re 100000;    
    }
    int vv=0;
    while('0'<=code[i][z+1]&&code[i][z+1]<='9')vv=vv*10+(code[i][++z]-48);
     re vv;
}

int check()
{
    stack<int>s;
    int flag=0,x,y,k,jj=0,jc=0,ans=0,cnt=0;
    
    for(int i=1;i<=n;++i)
    {
        if(c[i]=='F')
        {
            k=code[i][1]-'a'+1;
            if(vis[k])re -1;
            vis[k]=1;
            s.push(k);
            if(!flag)
            {
                z=2;x=gm(i);
                z++;y=gm(i);
                if(x>y)flag=k;
                else if(y-x>1000)
                ins[k]=1,ans=max(ans,++cnt);
            }
        }
        else 
        {
            if(s.empty())re -1;
            k=s.top();s.pop();
            vis[k]=0;
            if(flag==k)flag=0;
            else if(ins[k])cnt--,ins[k]=0;
        }
    }
    if(!s.empty())re -1;
    re ans;
}

int go(int x)
{
    int vv=0;
    while('0'<=o[x]&&o[x]<='9')vv=vv*10+(o[x++]-48);
    re vv;
}

int main()
{
//    freopen("in.txt","r",stdin);
    scanf("%d",&t);
    while(t--)
    {
        mem(vis,0);
        mem(ins,0);
        mem(c,0);
        int f=0;
        scanf("%d",&n);
        
        while(c[0]!='O')c[0]=getchar();
        getline(cin,o);
        if(o[1]=='n')f=1,w=go(3);
        else w=0;

        
        inc(j,1,n)
        {
            while(c[j]!=70&&c[j]!=69)c[j]=getchar();
            getline(cin,code[j]);            
        /*    inc(i,0,code[j].size())
            cout<<i<<" "<<code[j][i]<<endl;*/
        }    
        
        int ww=check();


        if(ww==-1)printf("ERR\n");
        else if(ww==w)printf("Yes\n");
        else printf("No\n");
    }

    return 0;
}
View Code

 

T3 逛公园

day 2

T1 奶酪

只有一千个点,那就n^2的暴力+并查集判联通呗,

#include<bits/stdc++.h>
using namespace std;
long long  t,n,h,r,u1,o1,r2;
struct node
{
long long x,y,z;    
}hollow[1505];
int fa[1505];

int find(long long x)
{
    if(fa[x]==x)return x;
    fa[x]=find(fa[x]);
    return fa[x];
}
 
bool judge(long long i,long long j)
{
    long long xx=abs(hollow[i].x-hollow[j].x),
        yy=abs(hollow[i].y-hollow[j].y),
        zz=abs(hollow[i].z-hollow[j].z);
    if(xx>r2||yy>r2||zz>r2)return 0;
    if(xx*xx+yy*yy+zz*zz>r2*r2)return 0;
    return 1;
}
int under[1001],over[1001];

int main()
{
    //freopen("pp.txt","r",stdin);
    //freopen("op.txt","w",stdout);
    scanf("%ld",&t);
    while(t>0)
    {
        memset(under,0,sizeof(under));
        memset(over,0,sizeof(over));
        scanf("%lld%lld%lld",&n,&h,&r);
        long long f=0;
        u1=o1=0;r2=2*r;t--;    
        for(long long i=1;i<=n;i++)
        {
        scanf("%lld%lld%lld",&hollow[i].x,&hollow[i].y,&hollow[i].z);
        if(hollow[i].z<=r)under[++u1]=i;
        if(h-hollow[i].z<=r)over[++o1]=i;    
        }
        
    
        for(long long i=1;i<=n;i++)
        fa[i]=i;
        
        for(long long i=1;i<=n;i++)
        for(long long j=i+1;j<=n;j++)
            {
            if(!judge(i,j))continue;
            fa[find(i)]=find(j);
            }
    
        for(long long i=1;i<=u1;i++)
        {
            for(int j=1;j<=o1;j++)
            if(find(under[i])==find(over[j]))
            {
                f=1;
                break;
            }
            if(f==1)break;
        }
        
     if(f==0)printf("No\n");
        else printf("Yes\n");
    }
    return 0;
}
View Code

 

T2 宝藏

仿佛记得机房某大佬有言:宝藏这个题本身就是一个宝藏

因为其极其n<=12的特征

所以理所当然不是暴力就是状压

dfs|随机化|状压都是ok的

然而我什么都不会…… 

 

70pts的dfs

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48) ;
    if(f)x=-x;
}

int n,m,d[20][20],dis[20];
int inf=555555555,ans=inf;
inline void dfs(int dep,int sum)
{
    if(sum>ans)re ;
    if(dep==n+1){
        if(ans==51&&sum<ans)
        ans=sum;
        ans=sum;
        re ;
    }
    inc(i,1,n)
    if(dis[i])
    {
        inc(j,1,n)
        if(!dis[j]&&d[i][j]!=inf)
        {
            dis[j]=dis[i]+1;
            dfs(dep+1,sum+dis[i]*d[i][j]);
            dis[j]=0;
        }
    }
}
int main()
{
    freopen("a.in","r",stdin);
    int x,y,z;
    rd(n),rd(m);
    inc(i,1,n)inc(j,1,n)d[i][j]=inf;
    inc(i,1,n)d[i][i]=0;
    inc(i,1,m)
    {
        rd(x),rd(y),rd(z);
        d[x][y]=d[y][x]=min(d[y][x],z);
    } 
/*    inc(k,1,n)inc(i,1,n)inc(j,1,n)
    d[i][j]=min(d[i][j],d[i][k]+d[k][j]);*/
    
    inc(i,1,n)
    {
        dis[i]=1;
        dfs(2,0);
        dis[i]=0;
    }
    printf("%d",ans) ;
    re 0;
}
View Code

 

 

 

T3 队列

正解树状数组不会

写过又臭又长的splay

当然最好还是权值线段树

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

#define ll long long
const int maxn=3e5+5;
ll n,m,Q;
ll T[maxn],ls[maxn<<5],rs[maxn<<5],num[maxn<<5];
ll use[maxn<<5];

ll tot,ans,flag;
inline void query(ll &rt,ll l,ll r,ll x)
{
    if(!rt)
    rt=++tot;
        ++use[rt];
    if(l==r)
    {
        if(num[rt])ans=num[rt];
        else if(!flag)ans=m*l;
        else ans=(flag-1)*m+l; 
        re ;
    }
    int mid=(l+r)>>1;
    int cnt=mid-l+1-use[ls[rt]];
     if(cnt>=x)query(ls[rt],l,mid,x);
     else query(rs[rt],mid+1,r,x-cnt);
}

inline void insert(ll &rt,ll l,ll r,ll pos)
{
    if(!rt)rt=++tot;
    if(l==r)
    {
        num[rt]=ans;
        re ;
    }
    ll mid=(l+r)>>1;
    if(pos<=mid)insert(ls[rt],l,mid,pos);
    else insert(rs[rt],mid+1,r,pos);
}

ll sum[maxn];
int main()
{
    freopen("b.in","r",stdin);
    ll x,y;
    rd(n),rd(m),rd(Q);
    inc(i,1,Q)
    {
        rd(x),rd(y);
        if(y==m)
        {
            flag=0;
            query(T[n+1],1,n+Q,x);
            printf("%lld\n",ans);
            ++sum[n+1];
            insert(T[n+1],1,n+Q,sum[n+1]+n);
        }
        else
        {
            flag=x;
            query(T[x],1,m+Q,y);
            printf("%lld\n",ans);
            ++sum[n+1];
            insert(T[n+1],1,n+Q,sum[n+1]+n);
            
            flag=0;
            query(T[n+1],1,n+Q,x);
            ++sum[x];
            insert(T[x],1,m+Q,sum[x]+m-1);
        }
    }
    re 0;
}
View Code

三.noip2016

day 1

T1 玩具谜题

zz模拟

 

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

#define dec(i,l,r) for(int i=l;i>=r;--i)
int n,m,f[100005];
string s[100005];
int main()
{
    freopen("b.in","r",stdin);
    rd(n),rd(m);
    inc(i,1,n)
    {
        rd(f[i]);
        cin>>s[i];
    }
    
    int now=1,x,y;
    inc(i,1,m)
    {
        rd(x),rd(y);
        if(!x)//左数 
        {
            if(f[now])
            {
                now+=y;
                if(now>n)now-=n;
            }
            else
            {
                now-=y;
                if(now<=0)now+=n;
            } 
        }
        else 
        {
            if(f[now])
            {
                now-=y;
                if(now<=0)now+=n;
            }
            else{
                now+=y;
                if(now>n)now-=n;
            }
        }
    }
    
    cout<<s[now];
    re 0;
}
View Code

 

T2 天天爱跑步

全场最难的题竟然放到了day1t2

有毒

估计也就只能骗部分分了

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

const int maxn=300005,maxz=600000,maxl=300000;
int n,m,k,hd[maxn],ans[maxn],val[maxn];
struct node
{
    int to,nt;
}e[maxn<<1];

inline void add(int x,int y)
{
    e[++k].to=y;e[k].nt=hd[x];hd[x]=k;
    e[++k].to=x;e[k].nt=hd[y];hd[y]=k;
}

struct solu{
    //分为s,t两部分
    int top,tot,cnt;
    int rt[maxn*30],sum[maxn*30][2],ls[maxn*30],rs[maxn*30],first[maxn];
    int rab[maxn*30];
    struct ll{
        int flag,op,val,nt;
    }st[maxn<<2];
    
    inline void insert(int x,int y,int z,int f)
    {
        st[++top]=(ll){f,z,y,first[x]};
        first[x]=top;
    }
    
    
    inline int New()
    {
        int now;
        if(tot)now=rab[tot--];
        else now=++cnt;
        ls[now]=rs[now]=sum[now][0]=sum[now][1]=0;
        re now;
    }
    inline void Throw(int x)
    {
        rab[++tot]=x;
    }
    
     
    inline int query(int rt,int l,int r,int pos,int f)
    {
        if(!rt)re 0;
        if(l==r)
            re sum[rt][f];
        int mid=(l+r)>>1;
        if(pos<=mid)re query(ls[rt],l,mid,pos,f);
        else re query(rs[rt],mid+1,r,pos,f);
    }
    
    inline void add(int &rt,int l,int r,int pos,int vvl,int f)
    {
        if(!rt) rt=New();
        if(l==r)
        {
            sum[rt][f]+=vvl;
            re ;
        }
        int mid=(l+r)>>1;
        if(pos<=mid)add(ls[rt],l,mid,pos,vvl,f);
        else add(rs[rt],mid+1,r,pos,vvl,f);
    }
    
    inline int merge(int x,int y,int l,int r)
    {
        if(!x||!y)re x+y;
        if(l==r)
        {

            sum[x][0]+=sum[y][0];
            sum[x][1]+=sum[y][1];
            Throw(y);
            re x;
        }
        
        int mid=(l+r)>>1;
        
        ls[x]=merge(ls[x],ls[y],l,mid);
        rs[x]=merge(rs[x],rs[y],mid+1,r);
        Throw(y);
        re x;
    }
}T;

struct Tree_lca
{
    int top[maxn],size[maxn],son[maxn],dep[maxn],fa[maxn];
    
    inline void dfs(int x)
    {
        dep[x]=dep[fa[x]]+(size[x]=1);
        for(int i=hd[x];i;i=e[i].nt)
        {
            int v=e[i].to;
            if(v!=fa[x])
            {
                fa[v]=x;
                dfs(v);
                size[x]+=size[v];
                if(size[v]>size[son[x]])son[x]=v;
            }
        }
    }
    
    inline void dfs2(int x,int topf)
    {
        top[x]=topf;
        if(son[x])
        {
            dfs2(son[x],topf);
            for(int i=hd[x];i;i=e[i].nt)
            {
                int v=e[i].to;
                if(!top[v])
                dfs2(v,v);
            }
        }
    }
    
    inline int Lca(int x,int y)
    {
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]])x^=y^=x^=y;
            x=fa[top[x]];
        }
        re dep[x]<dep[y]?x:y;
    }
        
}S;

inline void dfs(int x)
{
    for(int i=hd[x];i;i=e[i].nt)
    {
        int v=e[i].to;
        if(v!=S.fa[x])
        {
            dfs(v);
            if(x==1&&v==2)
            x=1; 
            T.rt[x]=T.merge(T.rt[x],T.rt[v],1,maxz);
        }
    }

    for(int i=T.first[x];i;i=T.st[i].nt)
        T.add(T.rt[x],1,maxz,T.st[i].val,T.st[i].op,T.st[i].flag);
    
    ans[x]=T.query(T.rt[x],1,maxz,S.dep[x]+val[x]+maxl,0);
    ans[x]+=T.query(T.rt[x],1,maxz,val[x]-S.dep[x]+maxl,1);
    
}

int main()
{
//    freopen("in.txt","r",stdin);
    int x,y,z;
    rd(n),rd(m);
    inc(i,2,n)
    {
        rd(x),rd(y);
        add(x,y); 
    }
    
    S.dfs(1);
    S.dfs2(1,n+1); 
    
    inc(i,1,n)
    rd(val[i]);
    
    inc(i,1,m)
    {
        rd(x),rd(y);
        int lca=S.Lca(x,y),flca=S.fa[lca];
        T.insert(x,S.dep[x]+maxl,1,0);T.insert(flca,S.dep[x]+maxl,-1,0);
        T.insert(y,S.dep[x]-(S.dep[lca]<<1)+maxl,1,1);T.insert(lca,S.dep[x]-(S.dep[lca]<<1)+maxl,-1,1);        
    }
    dfs(1);
    
    inc(i,1,n)
    printf("%d ",ans[i]);
    re 0;
}
View Code

 

T3换教室

遇到概率妥妥挂掉

呃……

虽然是模板题

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(long long i=l;i<=r;++i) 
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

const int maxn=2005;

#define ll long long 
ll n,m,v,e;
ll mp[maxn][maxn],c[maxn],d[maxn];
double f[maxn][maxn][2],p[maxn];

inline void floyd()
{
    inc(k,1,v)
    inc(i,1,v)
    inc(j,1,v)
        mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
    
}

int main()
{
    
//    freopen("in.txt","r",stdin);    
    rd(n),rd(m),rd(v),rd(e);
    ll x,y,z;
    
    inc(i,1,n)rd(c[i]);
    inc(i,1,n)rd(d[i]);
    inc(i,1,n)scanf("%lf",&p[i]);
    memset(mp,0x3f3f3f3f,sizeof mp);
    inc(i,1,v)mp[i][i]=0;
    inc(i,1,e)
    {
        rd(x),rd(y);
        rd(z);
        mp[x][y]=mp[y][x]=min(mp[x][y],z);
    }
    
    inc(i,1,n)inc(j,0,m)f[i][j][1]=f[i][j][0]=21174444;
    f[1][0][0]=0;
    f[1][1][1]=0;
    floyd();
    inc(i,2,n)
    inc(j,0,m)
    {
        f[i][j][0]=min(f[i-1][j][0]+mp[c[i-1]][c[i]],f[i-1][j][1]+(1-p[i-1])*mp[c[i-1]][c[i]]+p[i-1]*mp[d[i-1]][c[i]]);
        
        if(j)f[i][j][1]=min(f[i-1][j-1][0]+(1-p[i])*mp[c[i-1]][c[i]]+p[i]*mp[c[i-1]][d[i]],
                    f[i-1][j-1][1]+(1-p[i])*(1-p[i-1])*mp[c[i-1]][c[i]]
                    +p[i-1]*(1-p[i])*mp[d[i-1]][c[i]]+(1-p[i-1])*p[i]*mp[c[i-1]][d[i]]+p[i-1]*p[i]*mp[d[i-1]][d[i]]);
    }
    
    double ans=2147483647;
    inc(i,0,m)
    ans=min(ans,min(f[n][i][0],f[n][i][1]));
    printf("%.2lf",ans);
    re 0;
} 
View Code

  

day 2

T1 组合数问题

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

#define dec(i,l,r) for(int i=l;i>=r;--i)
const int maxn=2005;
int n,m,k,P,sum[maxn][maxn],c[maxn][maxn];

int main()
{
//    freopen("b.in","r",stdin);
    int T;
    rd(T);rd(P);
    c[0][0]=1;
    c[1][1]=c[1][0]=1;
    inc(i,2,2000)
    {
        c[i][0]=1;
        inc(j,1,i)
        {
            c[i][j]=(c[i-1][j-1]+c[i-1][j])%P;
            sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+(c[i][j]==0);
        }
        sum[i][i+1]=sum[i][i];
    }
    int x,y;
    while(T--)
    {
        rd(x),rd(y);
        if(y>x)y=x;
        printf("%d\n",sum[x][y]);
    } 
    re 0;
}
View Code

 

T2 蚯蚓

三个优队的故事

#include<bits/stdc++.h>
#define re return
#define dec(i,l,r) for(int i=l;i>=r;--i)
#define inc(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}
const int maxn=1e5+5;
#define ll long long
queue<ll>q1,q2,q3;
ll n,m,q,u,v,t,a[maxn],c[8000005];
double p;
inline ll Get_max()
{
    ll na,nb,nc;
    na=nb=nc=-99999999999999999;
    if(!q1.empty())na=q1.front();
    if(!q2.empty())nb=q2.front();
    if(!q3.empty())nc=q3.front();
    if(na>nb)
    {
        if(na>nc){q1.pop();re na;}
        else {q3.pop();re nc;}
    }
    else
    {
        if(nb>nc) {q2.pop();re nb;}
        else {q3.pop();re nc;}
    }
}
int main()
{
//  freopen("in.txt","r",stdin);
    scanf("%lld%lld%lld%lld%lld%lld",&n,&m,&q,&u,&v,&t);
    p=1.0*u/v;;
    inc(i,1,n)
    {
        rd(a[i]);
    }
    sort(a+1,a+n+1);
    dec(i,n,1)q1.push(a[i]);

    ll ic=0;
    inc(i,1,m)
    {
        ll T=Get_max();
        T+=ic;
        if(!(i%t))printf("%lld ",T);
        ic+=q;
        ll ta=(((int)(T*p))-ic);
        ll tb=(T-((int)(T*p)))-ic;
        if(ta>tb)
        swap(ta,tb);
        q2.push(tb);
        q3.push(ta);
    }

    printf("\n");
    int cnt=0;  
    while(!q1.empty())c[++cnt]=q1.front(),q1.pop();
    while(!q2.empty())c[++cnt]=q2.front(),q2.pop();
    while(!q3.empty())c[++cnt]=q3.front(),q3.pop();
    sort(c+1,c+cnt+1);
    inc(i,1,(n+m)/t)
    {
        printf("%lld ",c[n+m-i*t+1]+ic);
    }
    re 0;
} 
View Code

 

 T3 愤怒的小鸟

数据很小,状压

先处理出最多n^2的线

当然还阔以随机化

#include<bits/stdc++.h>
#define re return
#define st static
#define C  c=getchar()
#define mem(a,b) memset((a),(b),sizeof(a))
#define inc(i,l,r) for(int i=l;i<=r;++i)
#define dec(i,l,r) for(int i=l;i>=r;--i)
const double EPS=1e-9;

template<typename T>inline void read(T&x)
{
    char c;bool f=0;
    while((C)<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((C)>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48);
    if(f)x=-x;
}

using namespace std;

int t,n,m,best=0x3f3f3f3f,vis[20],mp[20];

double a,b;
struct node
{
    double x,y;
}e[20];

void cala(double x1,double y1,double x2,double y2)
{
    a=(y1*x2-y2*x1)/(x1*x2*(x1-x2));
    b=(y1-a*x1*x1)/x1;
}


int main()
{
//    freopen("in.txt","r",stdin);
    
    srand(time(NULL));
    inc(i,1,20)
    mp[i]=1<<(i-1);
    
    read(t);
    while(t--)
    {
        best=0x3f3f3f3f;
        read(n),read(m);
    
        for(int i=1;i<=n;i++)scanf("%lf%lf",&e[i].x,&e[i].y);
        
        inc(zz,1,60)
        {
            mem(vis,0);
            random_shuffle(e+1,e+n+1);
            
            int ans=0;
            inc(i,1,n)
            {
                if(vis[i])continue;
                vis[i]=1;    
                inc(j,i+1,n)
                {
                    if(vis[j])continue;
                    if(e[i].x==e[j].x)continue;
                     b=(e[i].y-e[j].y*(e[i].x*e[i].x)/(e[j].x*e[j].x))/(e[i].x-(e[i].x*e[i].x)/e[j].x);
                     a=(e[i].y-e[i].x*b)/(e[i].x*e[i].x);
                    if(a>=-EPS)continue;
                    vis[j]=1;
                    inc(k,j+1,n)if(fabs(e[k].y-a*e[k].x*e[k].x-b*e[k].x)<EPS)vis[k]=1;
                    break;
                }
                ans++;
            }
            best=min(best,ans);
            if(best==1)break;
        }    
        printf("%d\n",best);
    }
    
    re 0;
} 
View Code

每次枚举时,枚举一下当前未包含的点

#include<bits/stdc++.h>
#define re return
#define st static
#define C  c=getchar()
#define mem(a,b) memeset((a),(b),sizeof(a))
#define inc(i,l,r,c) for(int i=l;i<=r;i+=c)
#define dec(i,l,r,c) for(int i=l;i>=r;i-=c)
const double EPS=1e-6;

template<typename T>inline void read(T&x)
{
    char c;bool f=0;
    while((C)<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((C)>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48);
    if(f)x=-x;
}

using namespace std;
int t,n,m,dp[1<<20],vmp[1<<20],line[20][20];
double a,b,x[20],y[20];

void cala(double x1,double y1,double x2,double y2)
{
    a=(y1*x2-y2*x1)/(x1*x2*(x1-x2));
    b=(x1*x1*y2-x2*x2*y1)/(x1*x2*(x1-x2));
}


int main()
{
//    freopen("in.txt","r",stdin);
    for(int i=0;i<(1<<18);i++){ int j=1;for(;j<=18 && i&(1<<(j-1));j++);vmp[i]=j;}
    for(int i=1;i<=18;i++)line[i][0]=1<<(i-1);
    read(t);
    while(t--)
    {
        read(n),read(m);
        int ALL=(1<<n)-1;
        for(int i=1;i<=ALL;i++)dp[i]=1111111111;
        inc(i,1,n,1)inc(j,1,n,1)line[i][j]=0;
        
        int cnt=0;
        for(int i=1;i<=n;i++)scanf("%lf%lf",&x[i],&y[i]);
        
        for(int i=1;i<=n;++i)
        {
            for(int j=1;j<=n;++j)
            {    
                if(x[i]==x[j])continue;
                cala(x[i],y[i],x[j],y[j]);
                if(a>=0)continue;
                
                for(int k=1;k<=n;++k)
                    if(fabs(y[k]-a*x[k]*x[k]-b*x[k])<EPS)line[i][j]|=line[k][0];                
            }
        }
            
        
        for(int i=0;i<(1<<n);i++)
        {
            int j=vmp[i];
            for(int k=0;k<=n;k++)
                dp[i|line[j][k]]=min(dp[i|line[j][k]],dp[i]+1);
        }
        
        printf("%d\n",dp[(1<<n)-1]);
    }
    re 0;
} 
View Code

 

 

四.noip2015

day 1

 T1 神奇的幻方

按照说的做

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)

template<typename T>inline void read(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

using namespace std;
int n,a[50][50];

int main()
{
    read(n);
    int v=1,x=1,y=(n+1)>>1,z=n*n;a[x][y]=1;
    while(++v<=z)
    {
        if(x==1&&y!=n)x=n,y++;
        else if(x!=1&&y==n)x--,y=1;
        else if(x==1)x++;
        else 
        {
            if(!a[x-1][y+1])x--,y++;
            else x++;
        }
        if(x>n)x=1;
        if(y>n)y=1;
        a[x][y]=v;
    }
    
    inc(i,1,n)
    {
        inc(j,1,n)printf("%d ",a[i][j]);
        putchar('\n');
    }
    re 0;
}
View Code

T2 信息传递

找最小环

#include<bits/stdc++.h> 
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x; 
} 

const int maxn=2e5+5;
int n,m,d[maxn],hd[maxn];
struct node{
    int to,nt;
}e[maxn<<1];
int k;
inline void add(int x,int y){e[++k]=(node){y,hd[x]};hd[x]=k;++d[y];}

int c[maxn];
inline void topo()
{
    queue<int>q;
    inc(i,1,n)if(!d[i])q.push(i) ;
    while(!q.empty())
    {
        int x=q.front();
        c[x]=1;
        q.pop();
        for(int i=hd[x];i;i=e[i].nt)
        {
            int v=e[i].to;
            if(!(--d[v]))q.push(v);
        }
    }
}
int cnt,ans;
inline void dfs(int x)
{
    if(c[x])re ;
    c[x]=1;++cnt;
    for(int i=hd[x];i;i=e[i].nt)
    {
        int v=e[i].to;
        dfs(v);
    }
}
int main()
{
    freopen("b.in","r",stdin);
    rd(n);
    int x;
    inc(i,1,n)
    {
        rd(x);
        add(i,x);
    }
    topo();
    
    ans=n;    
    inc(i,1,n)
    if(!c[i])
    {
        cnt=0;
        dfs(i);
        ans=min(ans,cnt);
    }    
    
    printf("%d",ans);
    re 0;
}
View Code

T3 斗地主

玄学的搜索

#include<bits/stdc++.h>
#define re return
#define st static
#define inc(i,l,r) for(int i=l;i<=r;++i)
#define dec(i,l,r) for(int i=l;i>=r;--i)

template<typename T>inline void read(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')c=getchar();
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

using namespace std;
int a[20],t,n,ans;

void doudizhu(int x)
{
    if(x>ans)re;
    
    int k=0; 
    inc(i,3,14)//单顺子 
    if(!a[i])k=0;
    else
    {
        k++;
        if(k>=5)
        {
            inc(j,0,k-1)a[i-j]--;
            doudizhu(x+1);
            inc(j,0,k-1)a[i-j]++;    
        }    
    }
    
    k=0;
    inc(i,3,14)//双顺子
    if(a[i]<=1)k=0; 
    else 
    {
        k++;
        if(k>=3)
        {
            inc(j,0,k-1)a[i-j]-=2;
            doudizhu(x+1);
            inc(j,0,k-1)a[i-j]+=2;
        }
    }
    
    k=0;
    inc(i,3,14)//三顺子
    if(a[i]<=2)k=0; 
    else 
    {
        k++;
        if(k>=2)
        {
            inc(j,0,k-1)a[i-j]-=3;
            doudizhu(x+1);
            inc(j,0,k-1)a[i-j]+=3;
        }
    }
//------------------------------------------------------------------------------------------------------------------------------

    inc(i,2,14)
    {
        if(a[i]==4)//四带 
        {
            a[i]-=4;    
            
        
            inc(j,2,14)
            if(a[j]>=2)
            {
                a[j]-=2;
                inc(z,2,14)
                {
                    if(a[z]>=2)
                    {
                        a[z]-=2;
                        doudizhu(x+1);
                        a[z]+=2;
                    }
                }
                a[j]+=2;
            }
            
                  
           inc(j,2,15)   //四带二 
           {
               if(!a[j])continue;
               a[j]--;
               inc(z,2,15)
               if(a[z])
               {
                   a[z]--;
                   doudizhu(x+1);
                   a[z]++;
               }
               a[j]++;    
           } 
            
            doudizhu(x+1);
            a[i]+=4;
        }
        if(a[i]>=3)//三带 
        {
            a[i]-=3;
            inc(j,2,14)
            if(a[j]>=2)//三带二 
            {
            a[j]-=2;    
            doudizhu(x+1);
            a[j]+=2;    
            }
        
            inc(j,2,15)
            if(a[j]&&j!=i)//三带一 
            {
                a[j]--;
                doudizhu(x+1);
                a[j]++;
            }
            doudizhu(x+1);
            a[i]+=3;
        }
    }    
//------------------------------------------------------------------------------------------------------------------------
    inc(i,2,15)if(a[i])x++;
    ans=min(ans,x);
}


void vcc()
{
    int x,y;
    ans=23;
    memset(a,0,sizeof(a));
    inc(i,1,n)
    {
        read(x),read(y);
        if(!x)a[15]++;
        else if(x==1)a[14]++;
        else a[x]++;
    }
    doudizhu(0);
    printf("%d\n",ans);
}
int main()
{
//    freopen("testdata(1).in","r",stdin);
    
  /*  freopen("in.txt","r",stdin);*/
    read(t),read(n);
    while(t--)vcc();
    re 0;
}
View Code

day 2

T1 跳石头

贪心+二分

#include<bits/stdc++.h>
#define re return
#define sta static
#define supervisor liangsiyi.mz
#define inc(i,l,r) for(int i=l;i<=r;++i) 
#define dec(i,l,r) for(iny i=l;i>=r;--i)

using namespace std;
int n,k,l=1,r,m,ll,size,a[50005];

inline int read()
{
    int date=0;char c=' ';
    while('0'>c||c>'9')c=getchar();
    while('0'<=c&&c<='9'){date=(date<<3)+(date<<1)+(c^48);c=getchar();}
    re date;
}

bool jd(int floor)
{
    int tot=0,now=0;
    inc(i,1,n+1)
    if(a[i]-a[now]<floor)tot++;
    else now=i;
    
    if(tot<=m)re 1;
    else re 0;
}

int main()
{
    ll=read(),n=read(),m=read();

    inc(i,1,n)
        a[i]=read();
        a[n+1]=ll;
        if(n-m==0)r=ll;
    else r=ll/(n-m)+1;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(jd(mid))l=mid+1;
        else r=mid-1;
    }
    
    printf("%d",l-1);
    
    re 0;
}
View Code

T2 子串

dp

去年奇奇怪怪地写了过去

#include<bits/stdc++.h> 
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x; 
} 

#define ll long long
const int maxn=1e3+3;
ll n,m,k,f[2][205][205][2],P=1000000007;
char s1[maxn],s2[maxn];
int main()
{
    //freopen("b.in","r",stdin);
    rd(n),rd(m),rd(k);
    scanf("%s",s1+1);
    scanf("%s",s2+1);
    int now=1,pre=0;
    f[0][0][0][0]=f[1][0][0][0]=1;
    inc(i,1,n)
    {
        inc(j,1,m)
        inc(kk,1,k)
        {
            f[now][j][kk][0]=(f[pre][j][kk][0]+f[pre][j][kk][1])%P; 
            if(s1[i]==s2[j])
            {
                f[now][j][kk][1]=(f[pre][j-1][kk][1]+f[pre][j-1][kk-1][0]+f[pre][j-1][kk-1][1])%P;
            }
            else f[now][j][kk][1]=0;
        }
        
        now^=pre^=now^=pre; 
    }
    
    printf("%lld",(f[n&1][m][k][0]+f[n&1][m][k][1])%P);
    re 0;
}
View Code

T3 运输计划

二分+树上差分

#include<bits/stdc++.h>
#define inc(i,l,r) for(int i=l;i<=r;++i)
#define reg register
#define re     return

using namespace std;
const int maxn=300005,maxm=600005;

template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48);
    if(f)x=-x;
}
int n,m,k,k1,l,r,num,res,maxlen;
int to[maxm],nt[maxm],to1[maxm],val[maxm],nt1[maxm],head1[maxm],dis[maxn],head[maxn],faa[maxn],vis[maxn],cnt[maxn],a[maxn];


struct node
{
    int x,y,lca,dis;
}ask[maxn];

inline void add(int x=0,int y=0,int z=0)
{
    rd(x),rd(y),rd(z);
    to[++k]=y;nt[k]=head[x];val[k]=z;head[x]=k;
    to[++k]=x;nt[k]=head[y];val[k]=z;head[y]=k;
    r+=z;
}

inline void add1(int x,int y)
{
    nt1[++k1]=head1[x];head1[x]=k1;to1[k1]=y;
    nt1[++k1]=head1[y];head1[y]=k1;to1[k1]=x;
}
//-----------------------------------------tarjan------------------------------------------------//
inline int find(int x){re x==faa[x]?x:faa[x]=find(faa[x]);    }

void tarjan(int u,int fa)
{
    for(int i=head[u];i;i=nt[i])
    {
        int v=to[i],w=dis[u]+val[i];
        if(v==fa)continue;
        dis[v]=w;
        a[v]=w-dis[u];
        tarjan(v,u);
        int f1=find(v);
        int f2=find(u);
        if(f1!=f2)
            faa[f1]=find(f2);
        vis[v]=1;
    }
    
    for(int i=head1[u];i;i=nt1[i])
    {
        int v=to1[i];
        if(vis[v])
        {
            int now=(i+1)>>1;
            ask[now].lca=find(faa[v]);
            ask[now].dis=dis[v]+dis[u]-(dis[ask[now].lca]<<1);
            maxlen=max(ask[now].dis,maxlen);
        }
    }
}
//--------------------------------------------差分-----------------------------------------------//

void dfvv(int u,int fa)
{
    for(int i=head[u];i;i=nt[i])
    {
        int v=to[i];
        if(v!=fa)
        {
            dfvv(v,u);
            cnt[u]+=cnt[v];
        }
    }
    if(cnt[u]==num&&a[u]>res)res=a[u];    
} 

 inline bool check(int x)
 {
     memset(cnt,0,sizeof(cnt));
     
     res=num=0;
     for(int i=1;i<=m;i++)
     if(ask[i].dis>x) cnt[ask[i].x]++,cnt[ask[i].y]++,cnt[ask[i].lca]-=2,num++;
    
    dfvv(1,0);
    
     re maxlen-res<=x;
 }
//--------------------------------------------main-----------------------------------------------//
int main()
{    
    //freopen("testdata(2).in","r",stdin);
    //    freopen("in.txt","r",stdin);
    
    rd(n),rd(m);
    inc(i,2,n)add();
    inc(i,1,m){
        rd(ask[i].x),rd(ask[i].y);
        add1(ask[i].x,ask[i].y);
    }
    
    inc(i,1,n)faa[i]=i;
    tarjan(1,0);
    
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(check(mid))r=mid-1;
        else l=mid+1;
    }
    
    printf("%d",l);
    re 0;
}
View Code

 

五.noip2014

day 1

T1 生活大爆炸版石头剪刀布

zz 模拟

直接模拟打表就好

反正我看不出什么规律

#include<bits/stdc++.h>
#define re return
#define sta static
#define supervisor liangsiyi.mz
#define inc(i,l,r) for(int i=l;i<=r;++i) 
#define dec(i,l,r) for(int i=l;i>=r;--i)

using namespace std;
int n,cost[5][5]={0,0,1,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,1,1,0,0,0};
int a[205],b[205];
inline int read()
{
    int date=0;char c=' ';
    while('0'>c||c>'9')c=getchar();
    while('0'<=c&&c<='9'){date=(date<<3)+(date<<1)+(c^48);c=getchar();}
    re date;
}

void dfs()
{
    
    
}

int main()
{
    int x,y,sa=0,sb=0;;
    scanf("%d%d%d",&n,&x,&y);
    inc(i,1,x)
    scanf("%d",&a[i]);
    inc(i,1,y)
    scanf("%d",&b[i]);
    
    int i=0,j=0;
    inc(k,1,n)
    {
        i=(i+1)>x?1:i+1;
        j=(j+1)>y?1:j+1;
        sa+=cost[a[i]][b[j]];
        sb+=cost[b[j]][a[i]];
    }
    
    printf("%d %d",sa,sb);
}
View Code

 

T2 联合权值

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

typedef long long ll;
const int maxn=2e5+5;
ll n,m,w[maxn],P=10007,hd[maxn];
struct node{
    int to,nt;
}e[maxn<<1];
int k;
inline void add(int x,int y)
{
    e[++k]=(node){y,hd[x]};hd[x]=k;
}

ll ans=0,mmm;
inline void dfs(int x,int fa)
{
    ll sum=0,maxx=w[fa];
    for(int i=hd[x];i;i=e[i].nt)
    {
        int v=e[i].to;
        if(v==fa)continue;
        dfs(v,x);
        ans=(ans+(w[fa]+sum)*w[v])%P;
        mmm=max(mmm,w[v]*maxx);
        maxx=max(maxx,w[v]);
        sum=(sum+w[v])%P;
    }
}

int main()
{
    freopen("a.in","r",stdin);
    int x,y;
    rd(n);
    inc(i,2,n)
    {
        rd(x),rd(y);
        add(x,y);
        add(y,x);
    }
    
    inc(i,1,n)rd(w[i]);
    dfs(1,0);
    printf("%lld %lld",mmm,ans*2ll%P);
    re 0;
}
View Code

T3 飞扬的小鸟

背包

#include<bits/stdc++.h>
#define re return
#define sta static
#define supervisor liangsiyi.mz
#define ll long long
#define inc(i,l,r) for(int i=l;i<=r;++i) 
#define dec(i,l,r) for(int i=l;i>=r;--i)
#define M 0x3f3f3f3f

using namespace std;
int n,m,k,e[10005],xx[10005],yy[10005],l[10005],h[10005],f[10005][2005],x,y,z,ans; 
inline int read()
{
    int date=0;char c=' ';
    while('0'>c||c>'9')c=getchar();
    while('0'<=c&&c<='9'){date=(date<<3)+(date<<1)+(c^48);c=getchar();}
    re date;
}



int main()
{
//    freopen("testdata1.in","r",stdin);
    
    n=read(),m=read(),k=read();
    inc(i,1,n)h[i]=m,l[i]=1;
    inc(i,1,n)xx[i]=read(),yy[i]=read();
    inc(i,1,k)
    {x=read();y=read();z=read();
    e[x]=1;l[x]=y+1;h[x]=z-1;}
    
    memset(f,0x3f3f3f3f,sizeof(f));
    inc(i,1,m)f[0][i]=0;
    inc(i,1,n)
    {
        
        inc(j,xx[i]+1,m+xx[i])                                                    //浠?1  寮€  濮?锛?鍚?鍒?浼?閬?婕?
            f[i][j]=min(f[i-1][j-xx[i]]+1,f[i][j-xx[i]]+1);
        inc(j,m+1,m+xx[i])
            f[i][m]=min(f[i][m],f[i][j]);
        inc(j,1,m-yy[i])
            f[i][j]=min(f[i][j],f[i-1][j+yy[i]]);
        inc(j,1,l[i]-1)
            f[i][j]=M;
        inc(j,h[i]+1,m)
            f[i][j]=M;
    }    
    
        int sum=0x3f3f3f3f;
        inc(i,1,m)
        if(f[n][i])sum=min(sum,f[n][i]);
        
        if(sum!=0x3f3f3f3f)printf("1\n%d",sum);
        else 
        {
            dec(i,n,1)
            {    y=0;
                inc(j,1,m)
                if(f[i][j]<M)
                {
                    inc(k,1,i)
                    if(e[k])ans++;
                    printf("0\n%d",ans);
                    re 0;
                }            
            }    
        }
    re 0;
}
View Code

day 2

T1 无线网络发射器选址

二维前缀和

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}
using namespace std;
int n,m,d,a[150][150],ans,cnt;
int main()
{
    rd(d);
    rd(n);
    int k,x,y,l,r;
    inc(i,1,n)
    {
        rd(x),rd(y);
        rd(k);
        a[x+1][y+1]=k;
    }
    
    inc(i,1,129)inc(j,1,129)
    a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
    
    inc(i,1,129)inc(j,1,129)
    {
        l=i-d-1<0?0:i-d-1;
        r=i+d>129?129:i+d;
        x=j-d-1<0?0:j-d-1;
        y=j+d>129?129:j+d;
        k=a[y][r]-a[y][l]-a[x][r]+a[x][l];
        if(k>ans)ans=k,cnt=1;
        else if(ans==k)
        ++cnt;
    }
    
    printf("%d %d",cnt,ans);
    re 0;
}
View Code

貌似写法有点奇怪

 

T2 寻找道路

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

const int maxn=1e4+5,maxm=2e5+5;
int n,m,hd[maxn],vis[maxn],ok[maxn];
struct node{
    int to,nt;
}e[maxm<<1];
int k;
inline void add(int x,int y){
    e[++k]=(node){y,hd[x]};hd[x]=k;
}

inline void dfs(int x)
{
    vis[x]=ok[x]=1;
    for(int i=hd[x];i;i=e[i].nt)
    {
        int v=e[i].to;
        if(!vis[v])dfs(v);
    }
}

int dis[maxn],inf=5e5;
struct nide{
    int x,val;
    inline bool operator<(nide b)const {
        re val>b.val;
    }
};
int s,t;
inline void dij()
{
    inc(i,1,n)dis[i]=inf;
    priority_queue<nide>q;
    dis[t]=0;
    q.push((nide){t,0});
    while(!q.empty())
    {
        nide u=q.top();
        q.pop();
        int x=u.x;
        if(dis[x]!=u.val)continue;
        for(int i=hd[x];i;i=e[i].nt)
        {
            int v=e[i].to;
            if(ok[v]&&dis[v]>dis[x]+1)
            {
                dis[v]=dis[x]+1;
                q.push((nide){v,dis[v]});
            }
        }
    }
    if(dis[s]==inf)printf("-1");
    else printf("%d",dis[s]);
}
int main()
{
    freopen("a.in","r",stdin);
    rd(n),rd(m);
    int x,y;
    inc(i,1,m)
    {
        rd(x),rd(y);
        add(y,x);
    }
    rd(s),rd(t);
    dfs(t);
    vis[s]=1;
    inc(i,1,n)
    if(!vis[i])
    {
        for(int j=hd[i];j;j=e[j].nt)
        {
            int v=e[j].to;
            ok[v]=0;
        }
    }
    dij();
}
View Code

 

T3 解方程

多取几遍mod就好

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x; 
}

#define ll long long

ll mod[4]={47809,47807,102931,102929};
ll a[105][4],n,m;
char s[10005];

int cnt,ans[1000005];
bool vis[1000005];

inline bool check(int x)
{

    for(int i=0;i<4;++i)
    {
        ll tmp=a[n][i];
        for(int j=n-1;j>=0;--j)
            tmp=(tmp*x+a[j][i])%mod[i];
        
        if(tmp)
        {
            for(int j=x;j<=m;j+=mod[i])
            vis[j]=1;
            re 0;
        }
    }
    re 1;
}

int main()
{
    int len;
    rd(n),rd(m);
    inc(i,0,n)
    {
        scanf("%s",s+1);
        len=strlen(s+1);
        inc(k,0,3)
        {
            ll tmp=0,flag=1; 
            inc(j,1,len)
            if(s[j]=='-')flag=-1;
                else tmp=(tmp*10+(s[j]^48))%mod[k];
            a[i][k]=tmp*flag;
        } 
    }
    
    inc(i,1,m)
    if(!vis[i]&&check(i))ans[++cnt]=i;
    
    printf("%d\n",cnt);
    inc(i,1,cnt)
    printf("%d\n",ans[i]);
    re 0;
}
View Code

 

posted @ 2019-11-12 21:27  凉如水  阅读(222)  评论(0编辑  收藏  举报