2021寒假结训比赛

\(w[i][j] * w[j][k] * .... * w[p][i]<1成立\)

考试要认真看题啊哥!你怎么自动认为p i 是 p l呢。。。。。

\(圆周上面有n个位置可以绑上细线,可以这样把n个位置两两连接,然后在这个圆上产生很多的交点。\)
就是\(C(n,4)\)

CSU-1980 不堪重负的树

由于给出的是二叉树,且是中序遍历,所以该题可以用区间DP(枚举左端点和len)

        for(int l=2;l<=n;l++)
	{
	    for(int i=1;i+l-1<=n;i++)
		{
		 int j=i+l-1;
		 dp[i][j]=inf;
		 for(int k=i;k<=j;k++) 
		   dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]+sum[j]-sum[i-1]);
		}
		
	}

【BZOJ1575】【USACO 2009 OPEN】 气象牛Baric

f[i][j]表示最后一个i为必选,一共选了j个元素。

预处理三种误差:

1:从头到k的误差pre

2:从k到最后一个数的误差suf

3:【i+1,j-1】区间所有数对mid的误差

转移方程为:\(f[i][j]=min\{f[i][j],f[k][j-1]-suf[k]+med[k][i]+suf[i]\}\)

画个图就很直白了

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<math.h>
 5 //#include<iostream>
 6 using namespace std;
 7 
 8 int n,E;
 9 #define maxn 111
10 int suf[maxn],pre[maxn],med[maxn][maxn],f[maxn][maxn],a[maxn];
11 const int inf=0x3f3f3f3f;
12 int main()
13 {
14     scanf("%d%d",&n,&E);
15     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
16     for (int i=1;i<=n;i++)
17     {
18         pre[i]=0;
19         for (int j=1;j<i;j++)
20             pre[i]+=2*fabs(a[j]-a[i]);
21     }
22     for (int i=n;i>=1;i--)
23     {
24         suf[i]=0;
25         for (int j=i+1;j<=n;j++)
26             suf[i]+=2*fabs(a[j]-a[i]);
27     }
28     for (int i=1;i<=n;i++)
29         for (int j=i;j<=n;j++)
30         {
31             med[i][j]=0;
32             for (int k=i+1;k<j;k++)
33                 med[i][j]+=fabs(2*a[k]-a[i]-a[j]);
34         }
35     int ans=0,lest=inf;
36     for (int i=1;i<=n;i++)
37     {
38         f[i][1]=pre[i]+suf[i];
39         if (f[i][1]<=E) {ans=1;lest=min(lest,f[i][1]);}
40     }
41     for (int j=2;!ans && j<=n;j++)
42         for (int i=1;i<=n;i++)
43         {
44             f[i][j]=inf;
45             for (int k=1;k<i;k++)
46                 f[i][j]=min(f[i][j],f[k][j-1]-suf[k]+suf[i]+med[k][i]);
47             if (f[i][j]<=E) {ans=j;lest=min(lest,f[i][j]);}
48         }
49     printf("%d %d\n",ans,lest);
50     return 0;
51 }

5.CSU_1987

trie数,再加个数组纪录这个点的深度

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxl 10000010

using namespace std;

int n,sz,cas,cnt,ans;
int dis[maxl],val[maxl];
int ch[maxl][3];
char s[maxl];

void prework()
{
	memset(ch,0,sizeof(ch));
	memset(dis,0,sizeof(dis));
	memset(val,0,sizeof(val));
	scanf("%d",&n);
}

void insert()
{
	int len=strlen(s),u=0,v,c;
	for(int i=0;i<len;i++)
	{
		c=s[i]-'0';
		if(!ch[u][c])
		{
			sz++;ch[u][c]=sz;
			dis[sz]=dis[u]+1;
		}
		u=ch[u][c];
		val[u]++;
		if(val[u]*dis[u]>ans)
			ans=val[u]*dis[u];
	}
}

void mainwork()
{
	ans=0;sz=0;
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s);
		insert();
	}
}

void print()
{
	printf("%d\n",ans);
}

int main()
{
	int t;
	scanf("%d",&t);
	for(int i=1;i<=t;i++)
	{
		prework();
		mainwork();
		print();
	}
	return 0;
} 

6.区间内比k小的数

离线+树状数组

bool cmp1(const num &x,const num &y){
	return x.x<y.x;
}

bool cmp2(const que &x,const que &y){
	return x.x<y.x;
}

void prework(){
	n=read();m=read();
	for(int i=1;i<=n;i++)
		a[i].x=read(),a[i].ind=i,b[i]=0;
	sort(a+1,a+1+n,cmp1);
	for(int i=1;i<=m;i++){
		q[i].l=read();q[i].r=read();
		q[i].x=read();q[i].ind=i;
	}
	sort(q+1,q+1+m,cmp2);
}

void add(int i,int x){
	while(i<=n){
		b[i]+=x;
		i+=i&-i;
	}
}

int sum(int i)
{
	int s=0;
	while(i)
	{
		s+=b[i];
		i-=i&-i;
	}
	return s;
}

void mainwork()
{
	int at=0;
	for(int i=1;i<=m;i++)
	{
		while(at<n && a[at+1].x<q[i].x)
			at++,add(a[at].ind,1);
		ans[q[i].ind]=sum(q[i].r)-sum(q[i].l-1);
	}
}

CSUOJ 2151 区间赋值,区间加,使用分块与两个tag

#include<bits/stdc++.h>
#define N 100005
#define NN 500
#define ll long long
const int INF=1e9;
using namespace std;

int n,m,v0,a[N],num,block,belong[N],ri[N],le[N];
ll tag1[NN],tag2[NN];

long long sum[NN];

void build() { 
        block=sqrt(n); 
        num=n/block; 
        if(n%block) ++num; 
        for(int i=1 ; i <= n ; ++i) {
            belong[i]=(i-1)/block+1; 
        }
        for(int i=1 ; i <= num ; ++i) {
            le[i]=(i-1)*block+1;
            ri[i]=i*block; 
        }
        ri[num]=n; 
        for(int i=1 ; i <= num ; ++i) {
               for(int j=le[i] ; j <= ri[i] ; ++j) { 
                   sum[i] += a[j];
            }
        }
    } 
void Tagdown(int i){
    if(tag2[i]==-INF){
        if(tag1[i]!=-INF){
            sum[i]=0;
            for(int j=le[i];j<=ri[i];j++){
                a[j]+=tag1[i];
                sum[i]+=a[j];
            }
                 tag1[i]=-INF;
        }
    }
    else{
        sum[i]=0;
        for(int j=le[i];j<=ri[i];j++){
            a[j]=tag2[i];
            sum[i]+=a[j];
        }
        tag2[i]=-INF;
    }
}
void modify(int l,int r,int v,bool op) {  
        if(belong[l]==belong[r]){ 
                Tagdown(belong[l]);
                
                for(int i=l;i<=r;++i) { 
                    if(!op){
                        a[i] += v;
                        sum[belong[i]] += v;
                    } 
                    else{
                        sum[belong[i]] += (v-a[i]);
                        a[i]=v;
                    }
                }
                return;
        }  


            Tagdown(belong[l]);
            Tagdown(belong[r]);  



        for(int i=l;i <= ri[belong[l]];++i) { 
                if(!op){
                    a[i] += v;
                    sum[belong[i]] += v;
                } 
                else{
                    sum[belong[i]] += (v-a[i]);
                    a[i]=v;
                }
        }
        for(int i=le[belong[r]];i <= r;++i) { 
                if(!op){
                    a[i] += v;
                    sum[belong[r]]+=v;
                } 
                else{
                    sum[belong[i]] += (v-a[i]);
                    a[i]=v;
                }
        }

        for(int i=belong[l]+1 ; i<belong[r] ; ++i) { 
             if(!op){
                    if(tag2[i]!=-INF){
                        tag2[i] += v; 
                        sum[i]=tag2[i]*(ri[i]-le[i]+1);
                    }
                    else {
                        if(tag1[i]==-INF)tag1[i]=v;
                        else tag1[i] += v;
                        sum[i] += v*(ri[i]-le[i]+1);
                    }
                } 
                else{
                     tag2[i]=v;
                     tag1[i]=-INF;
                     sum[i]=v*(ri[i]-le[i]+1);
                }
        }  
}
//3.区间查询  
ll query(int l,int r) { 
 
        ll ans=0;

        
        if(belong[l]==belong[r]){
             for(int i=l;i <= r ;++i) {  
                if(tag2[belong[i]]!=-INF)ans += tag2[belong[i]];
                else if(tag1[belong[i]]!=-INF)ans += a[i]+tag1[belong[i]];
                else ans += a[i];
            }

            return ans;
        }

        for(int i=l;i <= ri[belong[l]];++i) {  
            if(tag2[belong[i]]!=-INF)ans += tag2[belong[i]];
            else if(tag1[belong[i]]!=-INF)ans += a[i]+tag1[belong[i]];
            else ans += a[i];
        }

        for(int i=le[belong[r]];i <= r;++i) { 
            if(tag2[belong[i]]!=-INF)ans += tag2[belong[i]];
            else if(tag1[belong[i]]!=-INF)ans += a[i]+tag1[belong[i]];
            else ans += a[i];
        } 
        for(int i=belong[l]+1 ; i<belong[r] ; ++i) {    
                   ans += sum[i];
        }  
        return ans;
}


int main(){

    scanf("%d%d%d",&n,&m,&v0); 
    for(int i=1;i <= n;i++)a[i]=v0;
    build();
    for(int i=1;i <= num;i++){
        tag1[i]=tag2[i]=-INF;
    }
    while(m--){
        int x,y,v,op;
        scanf("%d%d%d",&op,&x,&y);
        if(op!=2){
            scanf("%d",&v);
            modify(x,y,v,op);
        }
        else printf("%lld\n",query(x,y)); 
    }
    return 0; 
}
posted @ 2021-03-24 17:13  GUO_dx  阅读(28)  评论(0编辑  收藏  举报