11月9日——离noip还有10天

今天“贪心了”,然后GG地更凶了,连wyy都没考过;
哎,人生在世不称意,不如自挂东南枝;
昨天那份帖子一个晚上就有60多人看,好开心,
但是现在还是定格在60几
不bb了,直接上题。

子序列

每日图片
给定 3 个字符串,求它们的最长公共子序列。
输入
第一行一个整数 n,表示三个字符串的长度
接下来三行,每行是一个长度为 n 只包含小写字母的字符串。
输出
输出最长公共子序列的长度。

输入样例
4
abac
abbc
cbca

输出样例
2

提示
30% n<=10
100% n<=120

超级大水题

二维改三维

注意

ab与bc的lcs=1;
bc与ca的lcs=1;
ca与ab的lcs=1;
但是 ab与bc与ca的lcs=0;
所以一开始我的方法就GG了

正解

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<stack>
#define rez(i,x,y) for(int i=x;i>=y;i--)
#define res(i,x,y) for(int i=x;i<=y;i++)
#define minme(x,y) x=min(x,y)
#define INF 2100000000
#define ll long long
#define clr(x)  memset(x,0,sizeof(x))
#define N 100005
#define NAME "subq"

using namespace std;
char x[200],y[200],z[200];
int n;                       
int dp[200][200][200];
int LCS(){
    for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= n; ++j) {
            for(int k = 1; k <= n; ++k)
            {
                dp[i][j][k] = max(dp[i][j-1][k], dp[i-1][j][k]);
                dp[i][j][k] = max(dp[i][j][k], dp[i][j][k-1]);
                if(x[i] == y[j] && x[i] == z[k])
                dp[i][j][k] = max(dp[i][j][k], dp[i-1][j-1][k-1] + 1);
            }
        }
    }
    return dp[n][n][n];
}  
int main(){
    freopen(NAME".in","r",stdin);
    freopen(NAME".out","w",stdout);
    cin>>n;
    scanf("%s",x+1);
    scanf("%s",y+1);
    scanf("%s",z+1);
    int lcs_max_len=LCS();
    cout<<lcs_max_len<<endl;
    return 0;
}

dun

这里写图片描述
【问题描述】

定义两个素数是连续的当且仅当这两个素数之间不存在其他的素数(如
(7,11),(23,29)。给定N,k,在不超过N的正整数中求能够分解为k个连续的素数
的和的最大的那个是多少。

【输入格式】

第一行一个正整数T代表数据组数。
接下来T行每行两个正整数N, k代表一组询问。

【输出格式】

输出共T行,每行一个整数代表答案;如果找不到这样的数,输-1。

【样例输入】

3
20 2
20 3
20 4

【样例输出】

18
15
17

【样例解释】

╭︿︿︿╮
{/ o o /}
( (oo) )
︶︶︶
(说真的,好像认识一下这个把猪头当做样例解释的出题人)
【数据规模与约定】

对于20%的数据,1 <=N<=100。
对于40%的数据,T= 1。
对于60%的数据,所有的询问的N相等。
对于100%的数据,1<=T<=2000,1<=N<=10^6。

筛素数

先介绍网上广为流传的O(n)法,其实质是O(nloglogn)
借用这位博主的代码

void sieveTwo(){  
    int p,q;  
    int end = sqrt(N+0.5);  
    for(p = 2; p!=end; ++p ){  
        if(!arr[p]){  
            for(q = p; p*q <= N; ++q){  
                for(int k= p*q; k<= N; k*=p) arr[k] = 1;  
            }  
        }  
    }  
}  

虽然比起一般的筛法的确优一点,但并不是真正的O(n);
然后是杨z大神的代码(真正的可以近似达到O(n)的复杂度):
具体原因这位博主写得更详细。
这里不再赘述。

#include<cstdio>
#include<cstring>
#include<ctime>
#include<iostream>
#include<algorithm>
#define LL long long 
using namespace std;
const int N=1e7;
int prime[N+5],cnt,n,k,T,ans,pos;
bool mark[N+5];
LL sum[N+5];
int readint()
{
    int x=0; char ch=getchar();
    while (!isdigit(ch)) ch=getchar();
    while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();}
    return x;
}
void init()
{
    for (int i=2;i<=n;i++)
    {
        if (!mark[i]) prime[++cnt]=i;
        for (int j=1;j<=cnt;j++)
        {
            if (i*prime[j]>n) break;
            mark[i*prime[j]]=true;
            if (i%prime[j]==0) break;
        }
    }
    for (int i=1;i<=cnt;i++) sum[i]=sum[i-1]+prime[i];
}
int main()
{
    freopen("dun.in","r",stdin);
    cin>>n;
    init(); 
    //cout<<clock()<<endl<<endl;
    return 0;
}

小编用clock()测试了包括一般筛法在内的三种方法,结果如下:
这里写图片描述
可以看见最后一种既是O(n)的复杂度,要快很多。

题解

言归正传,这道题就可以先用任意一种较快的筛法,筛完后再用二分前缀和求解即可

code

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define LL long long 
using namespace std;
const int N=1e6;
int prime[N+5],cnt,n,k,T,ans,pos;
bool mark[N+5];
LL sum[N+5];
int readint()
{
    int x=0; char ch=getchar();
    while (!isdigit(ch)) ch=getchar();
    while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();}
    return x;
}
void init()
{
    for (int i=2;i<=N;i++)
    {
        if (!mark[i]) prime[++cnt]=i;
        for (int j=1;j<=cnt;j++)
        {
            if (i*prime[j]>N) break;
            mark[i*prime[j]]=true;
            if (i%prime[j]==0) break;
        }
    }
    for (int i=1;i<=cnt;i++) sum[i]=sum[i-1]+prime[i];
}
int main()
{
    freopen("dun.in","r",stdin);
    freopen("dun.out","w",stdout);
    init(); T=readint();
    while (T--)
    {
        n=readint(); k=readint(); ans=-1;
        pos=upper_bound(prime+1,prime+cnt+1,n)-prime-1;
        for (int i=pos;i>=k;i--) if (sum[i]-sum[i-k]<=n)
        {
            ans=sum[i]-sum[i-k];
            break;
        }
        printf("%d\n",ans);
    }
    return 0;
}

标答二

#include<cstdio>
#include<cstdlib>
#include<cstring>

using namespace std;

const int maxn=1000010;

int prime[maxn],cnt;

bool flag[maxn];

long long sum[maxn];

int main()
{
    for (int a=2;a<=1000000;a++)
    {
        if (!flag[a])
        {
            cnt++;
            prime[cnt]=a;
        }
        for (int b=1,c;b<=cnt && (c=a*prime[b])<=1000000;b++)
        {
            flag[c]=true;
            if (a % prime[b]==0) break;
        }
    }
    for (int a=1;a<=cnt;a++)
        sum[a]=prime[a]+sum[a-1];
    int t;
    scanf("%d",&t);
    for (;t--;)
    {
        int n,k;
        scanf("%d%d",&n,&k);
        int l=1,r=cnt-k+2;
        if (r<=1)
        {
            printf("-1\n");
            continue;
        }
        while (l+1!=r)
        {
            int m=(l+r)>>1;
            if (sum[m+k-1]-sum[m-1]>n) r=m;
            else l=m;
        }
        if (sum[l+k-1]-sum[l-1]<=n) printf("%d\n",(int)(sum[l+k-1]-sum[l-1]));
        else printf("-1\n");
    }

    return 0;
}

然后就可以AC

发放粮食

这里写图片描述
描述
有一个村庄在闹饥荒,善良而土豪的 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

什么树链剖分?不懂!!!
线段数+A*(启发式搜索)+内存回收乱搞,GG……
所以还是树链剖分吧!
学习中……请勿打扰

。。。。

崩掉的标答

#include <cstdio>

#include <cstring>

#include <vector>

#define lson rt<<1

#define rson rt<<1|1

#define maxn 100010

using namespace std;



struct Pair {

    int ind, val;

    Pair(){}

    Pair( int ii, int vv ) : ind(ii), val(vv) {}

};



int n, q;

vector<int> g[maxn], flag[maxn];

int siz[maxn], son[maxn], dep[maxn], pre[maxn], top[maxn], vid[maxn], id_clock;

int maxw, ans[maxn];

Pair seg[maxn<<2]; 



void input() {

    scanf( "%d%d", &n, &q );

    for( int i=1,u,v; i<n; i++ ) {

        scanf( "%d%d", &u, &v );

        g[u].push_back(v);

        g[v].push_back(u);

    }

}

void update( int w, int delta, int rt, int l, int r ) {

    if( l==r ) {

        seg[rt].val += delta;

        seg[rt].ind = l;

        return;

    }

    int mid = (l+r)>>1;

    if( mid>=w ) update( w, delta, lson, l, mid );

    else update( w, delta, rson, mid+1, r );

    seg[rt] = seg[lson].val < seg[rson].val ? seg[rson] : seg[lson];

}

void dfs1( int u ) {

    siz[u] = 1, son[u] = 0;

    for( int t=0; t<(int)g[u].size(); t++ ) {

        int v=g[u][t];

        if( v==pre[u] ) continue;

        dep[v] = dep[u]+1;

        pre[v] = u;

        dfs1(v);

        siz[u] += siz[v];

        son[u] = siz[v]>siz[son[u]] ? v : son[u];

    }

}

void dfs2( int u, int tp ) {

    top[u] = tp, vid[u] = ++id_clock;

    if( son[u] ) dfs2( son[u], tp );

    for( int t=0; t<(int)g[u].size(); t++ ) {

        int v=g[u][t];

        if( v==pre[u] || v==son[u] ) continue;

        dfs2( v, v );

    }

}

void build() {

    dep[1] = pre[1] = 1;

    dfs1(1);

    id_clock = 0;

    dfs2(1,1);

}

void modify( int u, int v, int w ) {

    while( top[u] != top[v] ) {

        if( dep[top[u]]<dep[top[v]] ) swap(u,v);

        flag[vid[top[u]]].push_back(w);

        flag[vid[u]+1].push_back(-w);

        u = pre[top[u]];

    }

    if( dep[u]<dep[v] ) swap(u,v);

    flag[vid[v]].push_back(w);

    flag[vid[u]+1].push_back(-w);

}

void answer() {

    for( int i=1; i<=q; i++ ) {

        int u, v, w;

        scanf( "%d%d%d", &u, &v, &w );

        modify( u, v, w );

        maxw = max( maxw, w );

    }

    for( int i=1; i<=id_clock; i++ ) {

        for( int t=0; t<(int)flag[i].size(); t++ ) {

            if( flag[i][t]>0 ) update( flag[i][t], 1, 1, 1, maxw );

            if( flag[i][t]<0 ) update( -flag[i][t], -1, 1, 1, maxw );

        }

        if( seg[1].val==0 ) ans[i] = 0;

        else ans[i] = seg[1].ind;

    }

    for( int i=1; i<=n; i++ )

        printf( "%d\n", ans[vid[i]] );

}

int main() {

    input();

    build();

    answer();

}

void pv( vector<int> &v ) {

    for( int t=0; t<(int)v.size(); t++ )

        fprintf( stderr, "%d ", v[t] );

    fprintf( stderr, "\n" );

}

(不懂为什么写一行空一行)

正确的标答

#include <iostream>
#include <map>
#define P(p) ((1)<<(p))
#define MAXP 15
using namespace std;

int n, q;
int head[100001], wght[100001], dest[200000], next[200000], etot;
int table[200000][MAXP+1], deep[100001], posn[100001], prev[100001], stot, maxp;
map<int,int> mp[100001];

void insert( int a, int b ) {
    etot++;
    dest[etot] = b;
    next[etot] = head[a];
    head[a] = etot;
}
void input() {
    ios::sync_with_stdio(false);
    cin>>n>>q;
    for( int i=1,a,b; i<n; i++ ) {
        cin>>a>>b;
        insert(a,b);
        insert(b,a);
    }
}
void dfst( int i, int f, int d ) {
    table[++stot][0] = i;
    posn[i] = stot;
    deep[i] = d;
    prev[i] = f;
    if( next[head[i]]==0 && dest[head[i]]==f ) return;
    for( int t=head[i]; t; t=next[t] ) {
        if( dest[t]==f ) continue;
        dfst(dest[t],i,d+1);
        table[++stot][0] = i;
    }
}
void makest() {
    dfst(1,1,1);
    for( maxp=MAXP; maxp>=0; maxp-- )
        if( P(maxp)<stot ) break;
    for( int p=1; p<=maxp; p++ )
        for( int i=1; stot-i+1>=P(p); i++ )
            table[i][p] = 
                deep[table[i][p-1]]<deep[table[i+P(p-1)][p-1]] 
                ? table[i][p-1] : table[i+P(p-1)][p-1];
}
int lca( int u, int v ) {
    u = posn[u];
    v = posn[v];
    if( u>v ) swap(u,v);
    for( int p=maxp; p>=0; p-- )
        if( P(p)<v-u+1 ) 
            return deep[table[u][p]]<deep[table[v-P(p)+1][p]]
                ? table[u][p]:table[v-P(p)+1][p];
        else if( P(p)==v-u+1 )
            return table[u][p];
    return 1<<31;
}
void dfs2( int i, int f ) {
    for( int t=head[i]; t; t=next[t] ) {
        if( dest[t]==f ) continue;
        dfs2(dest[t],i);
    }
    if( f==i ) return;
    for( map<int,int>::iterator it=mp[i].begin(); it!=mp[i].end(); it++ ) 
        mp[f][it->first] += it->second;
}
void work() {
    makest();
    while(q--) {
        int a, b, w, an;
        cin>>a>>b>>w;
        an = lca(a,b);
        mp[a][w]++;
        mp[b][w]++;
        mp[an][w]--;
        if( an!=1 ) mp[prev[an]][w]--;
    }
    dfs2(1,1);
    for( int i=1; i<=n; i++ ) {
        int xi=0, xv=0;
        for( map<int,int>::iterator it=mp[i].begin(); it!=mp[i].end(); it++ )
            if( xv<it->second ) {
                xi = it->first;
                xv = it->second;
            }
        cout<<xi<<endl;
    }
}
int main() {
    freopen("rice.in","r",stdin);
    freopen("rice.out","w",stdout);
    input();
    work();
}

何神的标答

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<iomanip>
#include<ctime>
#include<cctype>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
#define smax(x,tmp) x=max((x),(tmp))
#define smin(x,tmp) x=min((x),(tmp))
#define maxx(x1,x2,x3) max(max(x1,x2),x3)
#define minn(x1,x2,x3) min(min(x1,x2),x3)
typedef long long LL;
template <class T> inline void read(T &x)
{
    x = 0;
    T flag = 1;
    char ch = (char)getchar();
    while(ch<'0' || ch>'9')
    {
        if(ch == '-') flag = -1;
        ch = (char)getchar();
    }
    while(ch>='0' && ch<='9')
    {
        x = (x<<1) + (x<<3) + ch - '0';
        ch = (char)getchar();
    }
    x *= flag;
}
template <class T> T gcd(T a,T b) { return !b?a:gcd(b,a%b); }
// end template

const int INF=0x3f3f3f3f;
const int maxn = 100005;
int n,q,Root,maxw;
int ans[maxn];

// original tree related
struct Edge
{
    int to,next;
}edge[maxn<<1];
int head[maxn];
int maxedge;
inline void addedge(int u,int v)
{
    edge[++maxedge] = (Edge) { v,head[u] };
    head[u] = maxedge;
    edge[++maxedge] = (Edge) { u,head[v] };
    head[v] = maxedge;
}
// end original tree

// LCA related
const int maxd = 18;
const int D = 17;
int fa[maxn][maxd];
int depth[maxn];
void lca(int u,int father,int deep)
{
    depth[u] = deep;
    for(int k=1;k<=D;k++) fa[u][k] = fa[fa[u][k-1]][k-1];
    for(int i=head[u];~i;i=edge[i].next)
    {
        int v = edge[i].to;
        if(v == father) continue;
        fa[v][0] = u;
        lca(v,u,deep+1);
    }
}
int LCA(int u,int v)
{
    if(u == v) return u;
    if(depth[u] < depth[v]) swap(u,v);
    for(int k=D;k>=0;k--) if(depth[fa[u][k]] >= depth[v])
        u = fa[u][k];
    if(u == v) return u;
    for(int k=D;k>=0;k--) if(fa[u][k] ^ fa[v][k])
        u = fa[u][k] , v = fa[v][k];
    return fa[u][0];
}
// end LCA

// segment tree related
struct Node
{
    int ch[2];
    int pos,val; // the maxnode under this one and its value
    int size; // set for faster merge
}node[maxn<<5];
#define ch(x,d) node[x].ch[d]
#define size(x) node[x].size
#define pos(x) node[x].pos
#define val(x) node[x].val
int maxnode;
int sta[maxn<<5],top;
inline int require()
{
    int root;
    if(top) root = sta[top--];
    else root = ++maxnode;
    return root;
}
void recycle(int &root)
{
    if(!root) return;
    recycle(ch(root,0));
    recycle(ch(root,1));
    pos(root) = val(root) = 0;
    size(root) = 0;
    sta[++top] = root;
    root = 0;
}
inline void update(int root)
{
    size(root) = size(ch(root,0)) + size(ch(root,1));
    int lson = ch(root,0);
    int rson = ch(root,1);
    int rt = val(lson)>val(rson) || (val(lson)==val(rson)&&pos(lson)<pos(rson)) ? lson : rson; // the minimum type is required
    val(root) = val(rt);
    pos(root) = pos(rt);
}
void modify(int &root,int l,int r,int pos,int val)
{
    if(!root) root = require();
    if(l == r)
    {
        val(root) += val;
        pos(root) = l;
        size(root) = !!val(root);
        return;
    }
    int mid = (l+r)>>1;
    if(pos<=mid) modify(ch(root,0),l,mid,pos,val);
    else modify(ch(root,1),mid+1,r,pos,val);
    update(root);
}
void merge(int rt,int root,int l,int r)
{
    if(!size(root)) return;
    if(l == r)
    {
        modify(rt,1,maxw,l,val(root));
        return;
    }
    int mid = (l+r)>>1;
    merge(rt,ch(root,0),l,mid);
    merge(rt,ch(root,1),mid+1,r);
}
int ultra(int root1,int root2) // root2 to root1
{
    if(size(root1) < size(root2)) swap(root1,root2);
    merge(root1,root2,1,maxw);
    recycle(root2);
    return root1;
}
// end segment tree

// delta related
struct Delta
{
    int next;
    int pos;
    int val;
}delta[maxn<<2];
int d_pre[maxn],d_post[maxn];
int maxdelta;
inline void addpre(int u,int pos,int val)
{
    delta[++maxdelta] = (Delta) { d_pre[u],pos,val };
    d_pre[u] = maxdelta;
}
inline void addpost(int u,int pos,int val)
{
    delta[++maxdelta] = (Delta) { d_post[u],pos,val };
    d_post[u] = maxdelta;
}
// end delta

// main
inline void init()
{
    memset(head,-1,sizeof(head)); maxedge=-1;
    memset(d_pre,-1,sizeof(d_pre));
    memset(d_post,-1,sizeof(d_post));
    maxdelta=-1;
    read(n); read(q); Root = (n+1)>>1;
    for(int i=1;i<n;i++)
    {
        int x,y;
        read(x); read(y);
        addedge(x,y);
    }
    lca(Root,-1,1);
}
void delta_composition()
{
    for(int i=1;i<=q;i++)
    {
        int x,y,w;
        read(x),read(y),read(w); smax(maxw,w);
        int the_lca = LCA(x,y);
        addpre(x,w,1); addpre(y,w,1);
        addpre(the_lca,w,-1); addpost(the_lca,w,-1);
    }
}
int dfs(int u,int father)
{
    int root = require();
    for(int i=head[u];~i;i=edge[i].next)
    {
        int v = edge[i].to;
        if(v == father) continue;
        root = ultra(dfs(v,u),root);
    }
    for(int i=d_pre[u];~i;i=delta[i].next)
        modify(root,1,maxw,delta[i].pos,delta[i].val);
    ans[u] = pos(root);
    for(int i=d_post[u];~i;i=delta[i].next)
        modify(root,1,maxw,delta[i].pos,delta[i].val);
    return root;
}
void work()
{
    dfs(Root,-1);
    for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
}
int main()
{
    freopen("rice.in","r",stdin);
    freopen("rice.out","w",stdout);
    init();
    delta_composition();
    work();
    return 0;
}

综上所述,还是好好学习吧
GG

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值