[NOIP模拟][LCS][二分][树链剖分][hdu5029]

7 篇文章 0 订阅
3 篇文章 0 订阅

T1:
子序列
描述
给定3个字符串,求它们的最长公共子序列。
输入
第一行一个整数n,表示三个字符串的长度
接下来三行,每行是一个长度为n只包含小写字母的字符串。
输出
输出最长公共子序列的长度。
输入样例
4
abac
abbc
cbca
输出样例
2
提示
30% n<=10
100% n<=120

就是LCS 3维。。。,方程还是原来的他。。

T2:dun
【问题描述】
定义两个素数是连续的当且仅当这两个素数之间不存在其他的素数(如 7,11 ,(23,29)。给定��,��,在不超过��的正整数中求能够分解为��个连续的素数的和的最大的那个是多少。
【输入格式】
第一行一个正整数��代表数据组数。
接下来��行每行两个正整数��,��代表一组询问。
【输出格式】
输出共��行,每行一个整数代表答案;如果找不到这样的数,输出−1。
【样例输入】
3
20 2
20 3
20 4
【样例输出】
18
15
17
【样例解释】
╭︿︿︿╮
{/ o o /}
( (oo) )
︶︶︶
【数据规模与约定】
对于20%的数据,1≤��≤100。
对于40%的数据,��=1。
对于60%的数据,所有的询问的��相等。
对于100%的数据,1≤��<2000,1≤��≤106。

打出素数表,然后二分查找就好了。。。

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
#define INF 0x3f3f3f3f
#define clock CLOCKS_PER_SEC
#define cle(x) memset(x,0,sizeof(x))
#define maxcle(x) memset(x,127,sizeof(x))
#define mincle(x) memset(x,-1,sizeof(x))
#define cop(a,x) memcpy(x,a,sizeof(a))
#define FROP "dun"
#define C(a,b) next_permutation(a,b)
#define LL long long
#define smin(x,tmp) x=min(x,tmp)
#define maxx(x1,x2,x3) max(x1,max(x2,x3))
using namespace std;
const int N=80005,W=1e6;
int ss[N],tot,T,n,k;
bool vis[W+5];
LL sum[N];
void mack_ss()
{
    int q=sqrt(W+0.5);
    for(int j = 2; j <= q ; j++)
        for(int i = j * 2 ; i <= 1e6 ; i+=j)
        if(i%j==0&&!vis[i])
            vis[i]=true;
    vis[2]=false;
    vis[1]=true;
    for(int i = 1; i <= 1e6;i++)if(!vis[i])
            ss[++tot]=i;
    for(int i = 1; i <= tot;i++)
        sum[i]=sum[i-1]+ss[i];
}
int find(int x){
    int l=1,r=tot,ans;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(ss[mid]>=x)ans=mid,r=mid-1;
        else l=mid+1;
    }
    return ans;
}
int main()
{
    freopen(FROP".in","r",stdin);
    freopen(FROP".out","w",stdout);
    scanf("%d",&T);
    mack_ss();
    while(T--)
    {
        scanf("%d%d",&n,&k);
        int tmp=n/k;
        if(k*tmp!=n)tmp++;
        int w=find(tmp);
        LL ans=-1;
        for(int i = w, j = w+k-1; i >=1&&j>=1;i--,j--)
            if(sum[j]-sum[i-1]<=n)
            {
                ans=sum[j]-sum[i-1];
                break;
            }
        printf(AUTO"\n",ans);
    }
    return 0;
}

T3:发放粮食
描述
有一个村庄在闹饥荒,善良而土豪的YGH决定给他们发放救济粮,该村庄有 n 户人家,每两户人家之间只有一条路可以互相到达,即这些人家之间形成一棵树。现在 YGH 会以这样的形式给他们发放粮食,选择两户人家,然后对这两个户人家路径上的所有人家都发放一袋种类为 w 的救济粮。在完成一系列发放任务后,YGH 想知道每一户人家收到的粮食中数量最多的是哪一种。
输入
第一行两个数 n,q,其中 n 表示村庄共有几户人家,q 表示 YGH 一共发放了几次粮食。接下来 n-1 行,每行两个数 x y,表示编号为 x 和 y 的两户人家之间连有边。接下来 q 行,每行三个数 x y w,表示 YGH 选择了 x 到 y 的路径,对每户人家发放 1 袋种类为 w 的粮食。
输出
输出 n 行,第 i 行输出编号为 i 的人家收到的粮食中数量最多的种类号,如果有多个数量相同的粮食,输出其中最小的种类号,如果没有收到粮食,输出0
样例输入
[1]
2 4
1 2
1 1 1
1 2 2
2 2 2
2 2 1
[2]
5 3
1 2
3 1
3 4
5 3
2 3 3
1 5 2
3 3 3
样例输出
[1]
1
2
[2]
2
3
3
0
2
提示
对于 40% 的数据 n<=1000,q<=1000,1<=w<=1000
对于 100% 的数据 n<=100000,q<=100000,1<=w<=100000 1<=x,y<=n

是hdu5209原题,,还不会树链剖分,所以就用差分写的过了40

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
#define INF 0x3f3f3f3f
#define clock CLOCKS_PER_SEC
#define cle(x) memset(x,0,sizeof(x))
#define maxcle(x) memset(x,127,sizeof(x))
#define mincle(x) memset(x,-1,sizeof(x))
#define cop(a,x) memcpy(x,a,sizeof(a))
#define FROP "rice"
#define C(a,b) next_permutation(a,b)
#define LL long long
#define smin(x,tmp) x=min(x,tmp)
#define maxx(x1,x2,x3) max(x1,max(x2,x3))
using namespace std;
const int N=1e5+55;
int readin()
{
    int res=0;
    char ch=getchar();
    while(ch>'9'||ch<'0')ch=getchar();
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res;
}
struct ii
{
    int to,ne;
    ii(int to=0,int ne=0):to(to),ne(ne){ }
}ed[N*2];
struct qq
{
    int to,ne;
    qq(int to=0,int ne=0):to(to),ne(ne){ }
}que[N*2];
struct aa
{
    int x,y,w,lca;
    aa(int x=0,int y=0,int w=0):x(x),y(y),w(w){ }
    bool operator <(const aa &a)const
    {
        return w<a.w;
    }
}Q[N];
int head[N],fa[N],ufa[N],fir[N],n,q,vis[N];
int chan(int x){if(x%2)return (x+1)/2;return x/2;}
int find_fa(int x){return x==ufa[x]?x:ufa[x]=find_fa(ufa[x]);}
void init()
{
    n=readin(),q=readin();
    for(int i = 1; i <= n-1; i++)
    {
        int x=readin(),y=readin();
        ed[i*2-1]=ii(y,head[x]);
        head[x]=i*2-1;
        ed[i*2]=ii(x,head[y]);
        head[y]=i*2;
    }
    for(int i = 1; i <= q; i++)
    {
        int x=readin(),y=readin(),w=readin();
        que[i*2-1]=qq(x,fir[y]);
        fir[y]=i*2-1;
        que[i*2]=qq(y,fir[x]);
        fir[x]=i*2;
        Q[i]=aa(x,y,w);
    }
}
void tarjian(int u)
{
    ufa[u]=u;
    vis[u]=true;
    for(int i = head[u] ; i ; i =ed[i].ne)
    {
        int v=ed[i].to;
        if(fa[u]==v)continue;
        fa[v]=u;
        tarjian(v);
        ufa[v]=u;
    }
    for(int i = fir[u] ; i ; i = que[i].ne)
    {
        int v=que[i].to;
        if(!vis[v])continue;
        int p=chan(i);
        Q[p].lca=find_fa(v);
    }
}
int answ[N],ans[N];
int mer[N];
void cal(int x,int w)
{
    for(int i = head[x]; i ; i=ed[i].ne)
    {
        int v=ed[i].to;
        if(v==fa[x])continue;
        cal(v,w);
        mer[x]+=mer[v];
    }
    if(mer[x]==answ[x])smin(ans[x],w);
    else if(mer[x]>answ[x])
    {
        answ[x]=mer[x];
        ans[x]=w;
    }
}
void work()
{
    sort(Q+1,Q+q+1);
    int flag=Q[1].w;
    for(int i = 1; i <= q; i++)
    {
        if(flag!=Q[i].w)
        {
            cal(1,flag);
            flag=Q[i].w;
            cle(mer);
        }
        int x=Q[i].x,y=Q[i].y,lca=Q[i].lca;
        mer[x]++,mer[y]++,mer[lca]--;
        if(fa[lca])mer[fa[lca]]--;
    }
    cal(1,flag);
    for(int i = 1; i <= n; i++)
        printf("%d\n",ans[i]);
}
int main()
{
    freopen(FROP".in","r",stdin);
    freopen(FROP".out","w",stdout);
    init();
    tarjian(1);
    work();
    return 0;
}
/*
13 3
1 2 
1 3
2 3
2 5
6 3
7 3
8 4
4 9
8 10
8 11
9 12
9 13
10 5 100
12 6 100
6 7 20
*/

然后又把树链给学了,写了QAQ

#pragma comment(linker, "/STACK:1024000000,1024000000")  
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
#define INF 0x3f3f3f3f
#define clock CLOCKS_PER_SEC
#define cle(x) memset(x,0,sizeof(x))
#define maxcle(x) memset(x,127,sizeof(x))
#define mincle(x) memset(x,-1,sizeof(x))
#define minn(x1,x2,x3) min(x1,min(x2,x3))
#define cop(a,x) memcpy(x,a,sizeof(a))
#define FROP "rice"
#define C(a,b) next_permutation(a,b)
#define LL long long
#define smin(x,tmp) x=min(x,tmp)
using namespace std;
const int N=100010;
struct ii
{
    int to,ne;
    ii(int to=0,int ne=0):to(to),ne(ne){ }
}ed[N*2];
struct node
{
    int l,r;
    int val,key;
    node(int val=0,int key=0):val(val),key(key){ }
}col[N*4];
#define L(x) x<<1
#define R(x) (x<<1)|1
int fir[N],fa[N],son[N],top[N],tid[N],_tid[N],dep[N],siz[N],Index,n,m;
void dfs1(int u)
{
    siz[u]=1;
    for(int i =fir[u];i;i=ed[i].ne)
    {
        int v=ed[i].to;
        if(fa[u]==v)continue;
        fa[v]=u;
        dep[v]=dep[u]+1;
        dfs1(v);
        siz[u]+=siz[v];
        if(siz[v]>siz[son[u]])
            son[u]=v;
    }
}
void dfs2(int u,int tp)
{
    top[u]=tp;
    tid[u]=++Index;
    _tid[Index]=u;
    if(!son[u])return;
    dfs2(son[u],tp);
    for(int i = fir[u];i;i=ed[i].ne)
    {
        int v=ed[i].to;
        if(fa[u]==v||son[u]==v)continue;
        dfs2(v,v);
    }
}
#define val(x) col[x].val
#define key(x) col[x].key
#define l(x) col[x].l
#define r(x) col[x].r
void pushup(int u)
{
    val(u)=max(col[L(u)].val,col[R(u)].val);
    key(u)=val(R(u))>val(L(u))?key(R(u)):key(L(u));
}
void build(int l,int r,int u)
{
    l(u)=l,r(u)=r;
    if(l==r)
    {
        key(u)=l;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,L(u));
    build(mid+1,r,R(u));
}
void update(int tr,int pos,int v)
{
    if(l(tr)==pos&&pos==r(tr))
    {
        val(tr)+=v;
        return;
    }
    int mid=( l(tr) + r(tr) )>>1;
    if(mid>=pos)update(L(tr),pos,v);
    else update(R(tr),pos,v);
    pushup(tr);
}
vector<int>opt[N];
void sum(int x,int y,int v)
{
    opt[x].push_back(v);
    opt[y+1].push_back(-v);
}
void change(int x,int y,int v)
{
    int f1=top[x],f2=top[y];
    while(f1^f2)
    {
        if(dep[f1]<dep[f2])swap(f1,f2),swap(x,y);
        sum(tid[f1],tid[x],v);
        x=fa[f1];
        f1=top[x];
    }
    if(dep[x]>dep[y])swap(x,y);
    sum(tid[x],tid[y],v);
}
void init()
{
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n-1; i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        ed[i*2-1]=ii(y,fir[x]);
        fir[x]=i*2-1;
        ed[i*2]=ii(x,fir[y]);
        fir[y]=i*2;
    }
    dep[1]=1;dfs1(1),dfs2(1,1);
    int maxx=0;
    for(int i = 1; i <= m; i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        maxx=max(z,maxx);
        change(x,y,z);
    }
    build(1,maxx,1);
}
int ans[N];
void work()
{
    for(int i = 1; i<=n; i++)
    {
        int sz=opt[i].size();
        for(int j = 0; j<sz;j++)
        {
            int tmp=opt[i][j];
            if(tmp<0)update(1,-tmp,-1);
            else update(1,tmp,1);
        }
        ans[_tid[i]]=val(1)==0?0:key(1);
    }
    for(int i = 1; i<= n; i++)
        printf("%d\n",ans[i]);
}
int main()
{
    freopen(FROP".in","r",stdin);
    freopen(FROP".out","w",stdout);
    init();
    work();
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值