考试的时候刚了T1两个小时线段树写了三个子任务结果发现看错了题目,于是接下来一个半小时我自闭了

result=历史新低

这告诉我们,打暴力要端正态度,尤其是在发现自己之前出锅的情况下要保持心态的平和,不能和今天的比赛一样后面差不多直接弃疗


T1:

题意就是我们要做多次倒三角的区间加,最后统计全部的异或和。不幸的是当我看到空间限制512MB的时候就直接暴力上线段树了,凉心出题人

正解是很巧妙的二维前缀和做法

考虑我们暴力怎么做--对倒三角的每一行差分,最后统计一次,这样的复杂度是$O(nq)$的

这个时候可以发现每一次倒三角我们改变的差分序列是可以二维差分优化的。其实就是对三角的竖着的直角边和那条斜边在维护差分数组,最后再统计答案就好了

其他的做法不会啊,果然还是太弱

#include<algorithm>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<time.h>
using namespace std;
typedef long long ll; const int N=3e3+;
ll n,q;
ll a[N][N],b[N][N],c[N][N],d[N][N],e[N][N];
inline ll read()
{
char ch=getchar();
ll s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
int main()
{
freopen("u.in","r",stdin);
freopen("u.out","w",stdout);
//double st=clock();
n=read();q=read();
while (q--)
{
ll r=read(),c=read(),l=read(),s=read();
a[r][c]+=s;a[r+l][c]-=s;
b[r-c+n-][r]-=s;b[r-c+n-][r+l]+=s;
}
for (int i=;i<=n;i++)
for (int j=;j<=n;j++)
{
c[i][j]=c[i-][j]+a[i][j];
d[i][j]=d[i-][j-]+b[i-j+n][i];
e[i][j]=e[i][j-]+c[i][j]+d[i][j];
}
/*for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
printf("%d ",c[i][j]+d[i][j]);
printf("\n");
}*/
//printf("\n");
ll ans=;
for (int i=;i<=n;i++)
for (int j=;j<=n;j++) ans^=e[i][j];
/*for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++) printf("%d ",e[i][j]);
printf("\n");
}*/
printf("%lld\n",ans);
//double ed=clock();
//printf("%lf\n",ed-st);
}

T2:

数据范围好像就是给你状压DP的,状态分别是当前还剩下的球(一个0/1序列)和剩下球的个数(这里有个坑点,不能直接通过0/1序列记忆化,因为最高位可能是0,这样可能出现长度不同但是0/1序列相同的两个状态)

我们数组记忆化肯定是不行的,那么大的就只好开map了。鉴于上述的坑点,看代码注释了解如何避免吧

所谓最优策略,其实就是状态转移的时候取max就好

还有就是关于那个erase函数,删掉一个球,相当于在一个二进制数里面去掉一位。设去掉的二进制位为k,笔者的思路就是把0-k-1先取出来(预处理111...这样的数字&一下就好了),再把原来的数后面变成0(注意0的个数要比原来的位数少1,因为有一位被去掉了)

然后这题好像就A了,考场上像个傻叉一样的写搜索,关键是之前的1分暴力写完了没打return 0,输出两个答案的我彻底凉凉了,22分暴力都没有拿到

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<map>
using namespace std; const int N=;
int n,k;
int pre[N];
namespace calc
{
const int M=;
double a[<<M+];
map <int,double> p[N];
void init()
{
for (int i=;i<<<M+;i++) a[i]=-;
}
bool count(int bit,int len)
{
if (len<=M) return a[<<len|bit]!=-;//坑点处理在这儿,看到那个|没有?std太伟大了
else return p[len].count(bit);
}
double &find(int bit,int len)
{
if (len<=M) return a[<<len|bit];
else return p[len][bit];
}
}
int erase(int bit,int i)
{
return (bit&pre[i-])|((bit>>(i+))<<i);
}
double dfs(int bit,int len)
{
if (len<=k) return ;
if (calc::count(bit,len)) return calc::find(bit,len);//记忆化
double &res=calc::find(bit,len);
res=;
for (int i=,j=len-;i<=j;++i,--j)
{
if (i<j) res+=max(dfs(erase(bit,i),len-)+(bit>>i&),dfs(erase(bit,j),len-)+(bit>>j&))*;//*2是因为正的第i个,反的第len-i+1个也是这个位置
else res+=dfs(erase(bit,i),len-)+(bit>>i&);
}
return res/=len;//别忘了/len
}
int main()
{
//freopen("v.in","r",stdin);
//freopen("v.ans","w",stdout);
scanf("%d%d",&n,&k);
char ch[N];
scanf("%s",ch);
calc::init();
pre[]=;
for (int i=;i<N;i++) pre[i]=pre[i-]|(<<i);
int bit=;
k=n-k;
for (int i=;i<n;i++)
{
bit|=(ch[i]=='W')<<i;
}
printf("%.10lf\n",dfs(bit,n));
return ;
}

T3:

有两个需要明确的性质

1.不要变的边我们不变,因为变了我们还要至少花费一次代价把它变回来

2.一棵树里变了的边的条数就是在这些边覆盖的点集中奇数度数点的个数/2(度数是翻转的边带来的)。这个好像挺显然的,因为一条翻转的边只会给两个端点带来奇数的度数,中间的都是偶数的度数

考虑dp,dp[x][0/1]表示节点x与父亲的边是否翻转,最少的奇数点的个数和翻转的总长度(我们的dp数组存的这样的结构体)

发现目标是在最少的奇数点的基础上最小化翻转的总长度,也就是前者优先,于是我们用pair

考虑如何转移

设x与父亲的边的类型是type(if (d==2) type=2 else type=c^d)

如果type==1||type==2的话,dp[x][0]显然可以设成inf了,我们只能转移dp[x][1]。设tmp0表示仅仅考虑x的子树,当前点x不是路径端点的最小代价(注意x可能是被一条路径经过);tmp1表示仅仅考虑x的子树,当前点是路径端点的最小代价。这两个如何计算参见代码。dp[x][1]=max((tmp0.fi+1,tmp0.se+1),(tmp1.fi,tmp1.se+1))

还有就是type==0||type==2,这种情况也差不多,不理解参考代码吧

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#define pii pair<int,int>
using namespace std; const int N=1e5+;
const int inf=1e9+;
int n;
vector <pii> mp[N];
pii dp[N][];
inline int read()
{
char ch=getchar();
int s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
pii operator + (pii a,pii b){return make_pair(a.first+b.first,a.second+b.second);}
void dfs(int x,int fa,int type)
{
pii tmp0(,),tmp1(inf,inf);//tmp0是不以它为断电答案,tmp1是以它为端点的最小答案
for (int i=;i<mp[x].size();i++)
{
int y=mp[x][i].first;
if (y==fa) continue;
dfs(y,x,mp[x][i].second);
pii nxt0,nxt1;
nxt0=min(tmp0+dp[y][],tmp1+dp[y][]);
nxt1=min(tmp0+dp[y][],tmp1+dp[y][]);
tmp0=nxt0;tmp1=nxt1;
}
if (type==||type==)
{
dp[x][]=min(tmp0,make_pair(tmp1.first+,tmp1.second));
}
else dp[x][]=make_pair(inf,inf);
if (type==||type==)
{
dp[x][]=min(make_pair(tmp1.first,tmp1.second+),make_pair(tmp0.first+,tmp0.second+));
}
else dp[x][]=make_pair(inf,inf);
}
int main()
{
n=read();
for (int i=;i<n;i++)
{
int a=read(),b=read(),c=read(),d=read();
if (d!=) d=c^d;
mp[a].push_back(make_pair(b,d));
mp[b].push_back(make_pair(a,d));
}
dfs(,-,);
printf("%d %d\n",dp[][].first/,dp[][].second);
return ;
}

[雅礼NOIP2018集训 day3]的更多相关文章

  1. [雅礼NOIP2018集训] day6

    打满暴力好像是一种挑战,已经连续几天考试最后一个小时自闭了,因为自以为打完了暴力,然而,结果往往差强人意 大概是考试的策略有些问题 T1: 我们设$g[x]$为在x时取小于等于m个物品的最大价值,下面 ...

  2. [雅礼NOIP2018集训 day4]

    感觉状态极差啊,今天居然爆零了 主要是以下原因: 1.又是T1看错题肝了两个小时,发现题意理解错误瞬间心态爆炸 2.T2交错了文件名 3.T3暴力子任务和正解(假的)混在一起,输出了两个答案 都想为自 ...

  3. [雅礼NOIP2018集训 day1]

    现在才来填坑,之后还要陆续补其他几天的,可能前几天真的太颓了 T1: 题目大意:给定一个长度为n的序列,m次询问每次询问给出l,r,询问区间l到r的元素在模k意义下的最大值 数据范围当然是你暴力写不过 ...

  4. 雅礼 noip2018 模拟赛 day3 T3

    典型树形dp 这里,我们应该看到一些基本性质: ①:如果这个边不能改(不是没有必要改),我们就不改,因为就算改过去还要改回来,显然不是最优的 注意:"不能改"是指边的性质和要求的相 ...

  5. 雅礼 noip2018 模拟赛day3 T2

    典型的状压思想 设0表示黑球,1表示白球,用一串01序列代表剩下的球的状态,记f[i]表示在i状态下取球的最大期望 那么可以利用记忆化搜索更新,每一层枚举可能拿走的球然后向下搜索,同时记忆化即可 在状 ...

  6. [雅礼NOIP集训 2017] number 解题报告 (组合数+二分)

    题解: 令$S(i)={i+1,i+2,...,i<<1}$,f(i,k)表示S(i)中在二进制下恰好有k个1的数的个数 那么我们有$f(i,k)=\sum_{x=1}^{min(k,p) ...

  7. LOJ_6045_「雅礼集训 2017 Day8」价 _最小割

    LOJ_6045_「雅礼集训 2017 Day8」价 _最小割 描述: 有$n$种减肥药,$n$种药材,每种减肥药有一些对应的药材和一个收益. 假设选择吃下$K$种减肥药,那么需要这$K$种减肥药包含 ...

  8. 雅礼集训【Day6-1】字符串

    雅礼集训[Day6-1]字符串 假设我们有串\(a\),我们设\(a'\)为\(a\)翻转后按为取反过后的串. 我们只考虑前一半的,长为\(m\)的串.如果前半截匹配了\(a\)或者\(a'\),则\ ...

  9. 「雅礼集训 2017 Day7」事情的相似度

    「雅礼集训 2017 Day7」事情的相似度 题目链接 我们先将字符串建后缀自动机.然后对于两个前缀\([1,i]\),\([1,j]\),他们的最长公共后缀长度就是他们在\(fail\)树上对应节点 ...

随机推荐

  1. NEU 1006 Intermediary

    1006: Intermediary 时间限制: 1 Sec  内存限制: 128 MB提交: 261  解决: 25[提交][状态][讨论版] 题目描述 It is widely known tha ...

  2. SpringBoot项目部署

    项目背景     个人博客:http://www.huangyichun.cn/blog/8     采用SpringBoot开发的个人博客,部署到腾讯云服务器上,服务器系统为ubuntu16.04, ...

  3. UICollectionView的注册

    UICollectionView的dataSource中的item的注册 itme的注册和tableview中cell的创建是不同的 cell的创建是在cell中 而itme的注册是在viewDidL ...

  4. 什么时候使用try-catch

    上篇文章叙述了try-catch的效率问题,以及StackOverflow上各路大神们指出使用try-catch应该注意的一些问题. 这篇文章作为补充,转述下StackOverflow上各路大神对于何 ...

  5. 数据库SQL语句错误

      Caused by: android.database.sqlite.SQLiteException: near "where": syntax error(Sqlite co ...

  6. Windows2003 安装MVC4 环境的步骤

    一.作为部署服务器的安装步骤 1.服务器上安装SP2 和 IIS6 2.安装.Net Framework3.5 SP1(完整安装包,包含2.0 2.0SP1,237MB那个安装包) 3.安装.Net ...

  7. AARRR:互联网创业者一定要掌握的指标

    创业公司如何做数据分析?网站分析工具里的指标千百种,到底要从哪些数据入手呢?除了流量跟转换率,还有哪些数据跟公司成长有关呢?或许可以从了解AARRR Metrics开始.AARRR Metrics是由 ...

  8. Pyhton学习——Day30

    # 内核态# 用户态# 操作系统的运行是在BOIS启动盘读取代码,从硬盘读取到内存中,被操作系统的内核中,一直存在在内存中# 计算机系统的三层结构:应用软件-->操作系统-->硬件# 一般 ...

  9. node——try-catch与异步操作

    //try-catch,用于捕获异常 //try-catch在node中只能捕获同步的异常,不能捕获异步异常 var fs=require('fs'); /*fs.writeFile('./abc.t ...

  10. Python笔记(28)-----继承

    来自https://blog.csdn.net/sunwukong_hadoop/article/details/80175292 1.Python的继承以及调用父类成员 python子类调用父类成员 ...