[雅礼NOIP2018集训 day3]
考试的时候刚了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]的更多相关文章
- [雅礼NOIP2018集训] day6
打满暴力好像是一种挑战,已经连续几天考试最后一个小时自闭了,因为自以为打完了暴力,然而,结果往往差强人意 大概是考试的策略有些问题 T1: 我们设$g[x]$为在x时取小于等于m个物品的最大价值,下面 ...
- [雅礼NOIP2018集训 day4]
感觉状态极差啊,今天居然爆零了 主要是以下原因: 1.又是T1看错题肝了两个小时,发现题意理解错误瞬间心态爆炸 2.T2交错了文件名 3.T3暴力子任务和正解(假的)混在一起,输出了两个答案 都想为自 ...
- [雅礼NOIP2018集训 day1]
现在才来填坑,之后还要陆续补其他几天的,可能前几天真的太颓了 T1: 题目大意:给定一个长度为n的序列,m次询问每次询问给出l,r,询问区间l到r的元素在模k意义下的最大值 数据范围当然是你暴力写不过 ...
- 雅礼 noip2018 模拟赛 day3 T3
典型树形dp 这里,我们应该看到一些基本性质: ①:如果这个边不能改(不是没有必要改),我们就不改,因为就算改过去还要改回来,显然不是最优的 注意:"不能改"是指边的性质和要求的相 ...
- 雅礼 noip2018 模拟赛day3 T2
典型的状压思想 设0表示黑球,1表示白球,用一串01序列代表剩下的球的状态,记f[i]表示在i状态下取球的最大期望 那么可以利用记忆化搜索更新,每一层枚举可能拿走的球然后向下搜索,同时记忆化即可 在状 ...
- [雅礼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) ...
- LOJ_6045_「雅礼集训 2017 Day8」价 _最小割
LOJ_6045_「雅礼集训 2017 Day8」价 _最小割 描述: 有$n$种减肥药,$n$种药材,每种减肥药有一些对应的药材和一个收益. 假设选择吃下$K$种减肥药,那么需要这$K$种减肥药包含 ...
- 雅礼集训【Day6-1】字符串
雅礼集训[Day6-1]字符串 假设我们有串\(a\),我们设\(a'\)为\(a\)翻转后按为取反过后的串. 我们只考虑前一半的,长为\(m\)的串.如果前半截匹配了\(a\)或者\(a'\),则\ ...
- 「雅礼集训 2017 Day7」事情的相似度
「雅礼集训 2017 Day7」事情的相似度 题目链接 我们先将字符串建后缀自动机.然后对于两个前缀\([1,i]\),\([1,j]\),他们的最长公共后缀长度就是他们在\(fail\)树上对应节点 ...
随机推荐
- Android 开源框架ViewPageIndicator 和 ViewPager 仿网易新闻客户端Tab标签
转载请注明出处:http://blog.csdn.net/xiaanming/article/details/10766053 之前用JakeWharton的开源框架ActionBarSherlock ...
- ES JVM使用如果超过75%就会GC较多,导致ES索引性能下降
转自:https://www.elastic.co/guide/en/cloud/current/ec-metrics-memory-pressure.html Scenario: How Does ...
- Hessian Spirng实例
Spring实例 之前,我们做了很简单的纯Hessian的调用,虽然到此已经能够满足远程调用的需求了,但是我听说spring也能够访问hessian的远程服务,研究了一番,废话不多说,直接上示例. 业 ...
- 基于Redis实现分布式应用限流--转
原文地址:https://my.oschina.net/giegie/blog/1525931 摘要: 限流的目的是通过对并发访问/请求进行限速或者一个时间窗口内的的请求进行限速来保护系统,一旦达到限 ...
- VC工程里,如何编译汇编语言的文件
最近老是有朋友问,VC工程里,如何编译汇编语言的文件,接下来就说一下步骤: 1.将汇编语言文件,加入到工程里: 2.在Solution Explorer窗口中右键单击Visual C++项目,选择Bu ...
- 列表查询组件代码, 简化拼接条件SQL语句的麻烦
列表查询组件代码, 简化拼接条件SQL语句的麻烦 多条件查询
- hdu 5375 Gray code 【 dp 】
dp[i][j]表示第i位取j的时候取得的最大的分数 然后分s[i]是不是问号,s[i-1]是不是问号这大的四种情况讨论 #include<cstdio> #include<cstr ...
- 【AnjularJS系列6 】 过滤器
第六篇,过滤器 AngularJS 过滤器可用于转换数据: 过滤器 描述 currency 格式化数字为货币格式. filter 从数组项中选择一个子集. lowercase 格式化字符串为小写. o ...
- hp soap扩展最全说明,附天气预报调用的例子
自从php5开始,我们可以不用通过php nusoap来创建php soap web service 和调用 soap了,php5内置了 soap扩展.只需要在php.ini中开启soap的exten ...
- python中方法与函数的区别与联系
今天huskiesir在对列表进行操作的时候,用到了sorted()函数,偶然情况下在菜鸟教程上看到了内置方法sort,同样都可以实现我对列表的排序操作,那么方法和函数有什么区别和联系呢? 如下是我个 ...