(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
",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
",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
",query(x,y));
}
return 0;
}