TJOI2015 day2解题报告

其实第三题还没看啦~~前两题就总结下吧

T1:[TJOI2015]旅游

描述:(BZ没题面只能口述了。。)一个人在一棵树上走,每次从a->b会进行一次贸易(也就是在这条路径上买入物品然后在后面卖出)然后每次经过一个点该点的物品价格会上涨v,求每次贸易的最大获利

很裸的一道树链剖分,就是题目描述太不明白了。。这样就是在某条路径上找到某个点减去后面路径的最小点的值的最大值。可以用线段树的区间合并解决。就是在求答案时的合并答案上方向搞反了查了很久。。。以前也犯过着种错误,以后不能再犯了。。

CODE:

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 using namespace std;
  7 #define maxn 50010
  8 vector<int> e[maxn];
  9 #define pb push_back
 10 int add[maxn],pre[maxn],fa[maxn],pos[maxn];
 11 int n;
 12 inline void bfs() {
 13     static int q[maxn],s[maxn],ch[maxn];
 14     q[1]=1;
 15     for (int l=1,r=1,u=q[l];l<=r;u=q[++l])
 16         for (int i=0;i<e[u].size();i++)
 17             if (e[u][i]!=fa[u]) {
 18                 fa[e[u][i]]=u;
 19                 q[++r]=e[u][i];
 20             }
 21     for (int i=n,u=q[n];i;u=q[--i]) {
 22         s[u]++;
 23         s[fa[u]]+=s[u];
 24         ch[fa[u]]=s[ch[fa[u]]]<s[u]?u:ch[fa[u]];
 25     }
 26     int cnt=0;
 27     for (int i=1,u=q[1];i<=n;u=q[++i]) {
 28         if (add[u]!=0) continue;
 29         pos[add[u]=++cnt]=u;pre[u]=u;
 30         for (u=ch[u];u;u=ch[u]) {
 31             pos[add[u]=++cnt]=u;pre[u]=pre[fa[u]];
 32         }
 33     }
 34 }
 35 typedef long long ll;
 36 struct b {
 37     ll mx,mn,ans[2];
 38     b() {mx=mn=ans[0]=ans[1]=0;}
 39 };
 40 inline b update(b l,b r) {
 41     b ans;
 42     ans.mx=max(l.mx,r.mx);
 43     ans.mn=min(l.mn,r.mn);
 44     ans.ans[0]=max(max(l.ans[0],r.ans[0]),l.mx-r.mn);
 45     ans.ans[1]=max(max(l.ans[1],r.ans[1]),r.mx-l.mn);
 46     return ans;
 47 }
 48 inline b rec(b x) {
 49     swap(x.ans[0],x.ans[1]);
 50     return x;
 51 }
 52 struct node {
 53     int l,r,lz;b bo;
 54 }t[maxn*8];
 55 #define lc (x<<1)
 56 #define rc (lc^1)
 57 #define mid ((l+r)>>1)
 58 int a[maxn];
 59 void build(int x,int l,int r){
 60     t[x].l=l,t[x].r=r;
 61     if (l==r) {
 62         t[x].bo.mx=t[x].bo.mn=a[pos[l]];
 63         t[x].bo.ans[0]=t[x].bo.ans[1]=0;
 64         return ;
 65     }
 66     build(lc,l,mid);build(rc,mid+1,r);
 67     t[x].bo=update(t[lc].bo,t[rc].bo);
 68 }
 69 inline void pb(int x) {
 70     if (t[x].lz==0) return ;
 71     if (t[x].l!=t[x].r) {
 72         t[lc].lz+=t[x].lz;
 73         t[lc].bo.mn+=t[x].lz;
 74         t[lc].bo.mx+=t[x].lz;
 75         t[rc].lz+=t[x].lz;
 76         t[rc].bo.mn+=t[x].lz;
 77         t[rc].bo.mx+=t[x].lz;
 78     }
 79     t[x].lz=0;
 80 }
 81 inline b change(int x,int x1,int y1,int z) {
 82     int l=t[x].l,r=t[x].r;
 83     pb(x);
 84     if (x1<=l&&r<=y1) {
 85         t[x].lz+=z;
 86         t[x].bo.mn+=z;
 87         t[x].bo.mx+=z;
 88         return t[x].bo;
 89     }
 90     b ans;
 91     if (mid>=y1) ans=change(lc,x1,y1,z);
 92     else if (mid<x1) ans=change(rc,x1,y1,z);
 93     else ans=update(change(lc,x1,y1,z),change(rc,x1,y1,z));
 94     t[x].bo=update(t[lc].bo,t[rc].bo);
 95     return ans;
 96 }
 97 inline b set(int x,int y,int z) {
 98     int c[2]={x,y};
 99     b ans[2];
100     bool bo[2]={0,0};
101     while (c[0]!=c[1]) {
102         int l=add[c[1]]<add[c[0]]?0:1;
103         if (pre[c[l]]==pre[c[l^1]]) {
104             if (bo[l]) ans[l]=update(change(1,add[c[l^1]]+1,add[c[l]],z),ans[l]);
105             else ans[l]=change(1,add[c[l^1]]+1,add[c[l]],z);
106             c[l]=c[l^1];
107         } else {
108             if (bo[l]) ans[l]=update(change(1,add[pre[c[l]]],add[c[l]],z),ans[l]);
109             else ans[l]=change(1,add[pre[c[l]]],add[c[l]],z);
110             c[l]=fa[pre[c[l]]];
111         }
112         bo[l]=1;
113     }
114     b _ans=change(1,add[c[0]],add[c[0]],z);
115     if (bo[0]) _ans=update(rec(ans[0]),_ans);
116     if (bo[1]) _ans=update(_ans,ans[1]);
117     return _ans;
118 }
119 int main(){
120     freopen("travel.in","r",stdin);
121     freopen("travel.out","w",stdout);
122     scanf("%d",&n);
123     for (int i=1;i<=n;i++) scanf("%d",a+i);
124     for (int i=1;i<n;i++) {
125         int x,y;
126         scanf("%d%d",&x,&y);
127         e[x].pb(y);e[y].pb(x);
128     }
129     bfs();
130     build(1,1,n);
131     int Q;
132     scanf("%d",&Q);
133     while (Q--) {
134         int x,y,v;
135         scanf("%d%d%d",&x,&y,&v);
136         b ans=set(x,y,v);
137         printf("%d\n",ans.ans[1],ans.ans[1],ans.mx,ans.mn);
138     }
139     return 0;
140 }

T2:[TJOI2015]棋盘

就是一道状态压缩+矩阵乘法。

首先我们可以先状压一下,可以发现每次的转移都是相同的,然后就能用矩阵乘法优化了

CODE:

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 using namespace std;
  7 #define maxn 50010
  8 vector<int> e[maxn];
  9 #define pb push_back
 10 int add[maxn],pre[maxn],fa[maxn],pos[maxn];
 11 int n;
 12 inline void bfs() {
 13     static int q[maxn],s[maxn],ch[maxn];
 14     q[1]=1;
 15     for (int l=1,r=1,u=q[l];l<=r;u=q[++l])
 16         for (int i=0;i<e[u].size();i++)
 17             if (e[u][i]!=fa[u]) {
 18                 fa[e[u][i]]=u;
 19                 q[++r]=e[u][i];
 20             }
 21     for (int i=n,u=q[n];i;u=q[--i]) {
 22         s[u]++;
 23         s[fa[u]]+=s[u];
 24         ch[fa[u]]=s[ch[fa[u]]]<s[u]?u:ch[fa[u]];
 25     }
 26     int cnt=0;
 27     for (int i=1,u=q[1];i<=n;u=q[++i]) {
 28         if (add[u]!=0) continue;
 29         pos[add[u]=++cnt]=u;pre[u]=u;
 30         for (u=ch[u];u;u=ch[u]) {
 31             pos[add[u]=++cnt]=u;pre[u]=pre[fa[u]];
 32         }
 33     }
 34 }
 35 typedef long long ll;
 36 struct b {
 37     ll mx,mn,ans[2];
 38     b() {mx=mn=ans[0]=ans[1]=0;}
 39 };
 40 inline b update(b l,b r) {
 41     b ans;
 42     ans.mx=max(l.mx,r.mx);
 43     ans.mn=min(l.mn,r.mn);
 44     ans.ans[0]=max(max(l.ans[0],r.ans[0]),l.mx-r.mn);
 45     ans.ans[1]=max(max(l.ans[1],r.ans[1]),r.mx-l.mn);
 46     return ans;
 47 }
 48 inline b rec(b x) {
 49     swap(x.ans[0],x.ans[1]);
 50     return x;
 51 }
 52 struct node {
 53     int l,r,lz;b bo;
 54 }t[maxn*8];
 55 #define lc (x<<1)
 56 #define rc (lc^1)
 57 #define mid ((l+r)>>1)
 58 int a[maxn];
 59 void build(int x,int l,int r){
 60     t[x].l=l,t[x].r=r;
 61     if (l==r) {
 62         t[x].bo.mx=t[x].bo.mn=a[pos[l]];
 63         t[x].bo.ans[0]=t[x].bo.ans[1]=0;
 64         return ;
 65     }
 66     build(lc,l,mid);build(rc,mid+1,r);
 67     t[x].bo=update(t[lc].bo,t[rc].bo);
 68 }
 69 inline void pb(int x) {
 70     if (t[x].lz==0) return ;
 71     if (t[x].l!=t[x].r) {
 72         t[lc].lz+=t[x].lz;
 73         t[lc].bo.mn+=t[x].lz;
 74         t[lc].bo.mx+=t[x].lz;
 75         t[rc].lz+=t[x].lz;
 76         t[rc].bo.mn+=t[x].lz;
 77         t[rc].bo.mx+=t[x].lz;
 78     }
 79     t[x].lz=0;
 80 }
 81 inline b change(int x,int x1,int y1,int z) {
 82     int l=t[x].l,r=t[x].r;
 83     pb(x);
 84     if (x1<=l&&r<=y1) {
 85         t[x].lz+=z;
 86         t[x].bo.mn+=z;
 87         t[x].bo.mx+=z;
 88         return t[x].bo;
 89     }
 90     b ans;
 91     if (mid>=y1) ans=change(lc,x1,y1,z);
 92     else if (mid<x1) ans=change(rc,x1,y1,z);
 93     else ans=update(change(lc,x1,y1,z),change(rc,x1,y1,z));
 94     t[x].bo=update(t[lc].bo,t[rc].bo);
 95     return ans;
 96 }
 97 inline b set(int x,int y,int z) {
 98     int c[2]={x,y};
 99     b ans[2];
100     bool bo[2]={0,0};
101     while (c[0]!=c[1]) {
102         int l=add[c[1]]<add[c[0]]?0:1;
103         if (pre[c[l]]==pre[c[l^1]]) {
104             if (bo[l]) ans[l]=update(change(1,add[c[l^1]]+1,add[c[l]],z),ans[l]);
105             else ans[l]=change(1,add[c[l^1]]+1,add[c[l]],z);
106             c[l]=c[l^1];
107         } else {
108             if (bo[l]) ans[l]=update(change(1,add[pre[c[l]]],add[c[l]],z),ans[l]);
109             else ans[l]=change(1,add[pre[c[l]]],add[c[l]],z);
110             c[l]=fa[pre[c[l]]];
111         }
112         bo[l]=1;
113     }
114     b _ans=change(1,add[c[0]],add[c[0]],z);
115     if (bo[0]) _ans=update(rec(ans[0]),_ans);
116     if (bo[1]) _ans=update(_ans,ans[1]);
117     return _ans;
118 }
119 int main(){
120     freopen("travel.in","r",stdin);
121     freopen("travel.out","w",stdout);
122     scanf("%d",&n);
123     for (int i=1;i<=n;i++) scanf("%d",a+i);
124     for (int i=1;i<n;i++) {
125         int x,y;
126         scanf("%d%d",&x,&y);
127         e[x].pb(y);e[y].pb(x);
128     }
129     bfs();
130     build(1,1,n);
131     int Q;
132     scanf("%d",&Q);
133     while (Q--) {
134         int x,y,v;
135         scanf("%d%d%d",&x,&y,&v);
136         b ans=set(x,y,v);
137         printf("%d\n",ans.ans[1],ans.ans[1],ans.mx,ans.mn);
138     }
139     return 0;
140 }

T3写完再补上吧。。。

话说BZ 350道题了。。。其实这一年几乎都在学校的oj上刷,能在这1年的时间刷多了100道题也挺自豪的。。。想想自己100时的那种兴奋,还是觉得自己挺弱智的。。。

还有3个小时就是自己的17岁生日了,回想自己的第16个年头,还是挺满意的,至少自己坚持了自己的路。在这里祝自己生日快乐,在接下来的一年里会接受越来越大的挑战,或者省队都进不了直接滚粗,或者noi胸牌滚粗,又或者侥幸成为了进队爷。。。不管自己今后咋样,希望能不忘本心吧,自己选择的路,就算跪着也要走完。

距GDOI还有4天,明天就是最后的一场模拟赛了,自己却感觉还总是找不到感觉,真的不想再发生像NOIP还有GDKOI时那黑暗的第二天了。。。自己真的很想被人敬仰膜拜一番,加油吧,再认真仔细一点吧。

以后的路会怎样,就跟我现在在听的歌一样吧。God knows,只有上帝才会知道,我们现在所能做的,只有认真过好每一分每一秒了

GDOI,God Bless!!!

时间: 2024-10-13 16:07:41

TJOI2015 day2解题报告的相关文章

常州培训 day2 解题报告

第一题: 题目大意: 给出一个M面的骰子,投N次,求最大期望值. 最大期望值的定义: 比如M=2,N=2, 那么 2次可以是 1,1,最大值为1: 1,2最大值为2: 2,1最大值为2: 2,2 最大值为2: 最大期望值就是  (1+2+2+2)/4=1.75 也就是把所有情况的最大值加起来,除以方案数.M,N<=5000 解题过程:1.这题只能说自己数学水平不够,只能找找规律骗点分,竟然混了个40分.小的数据直接模拟,拿40分. 2.正解: 考虑最大值为1的情况,sum=1*(1^N-0^N)

NOIp 2013 Day2 解题报告

NOIp 2013 Day2 解题报告 1.   积木大赛 每次只要选取连续最大的一段区间即可. 继续归纳可得,答案为∑i=1nmax{0,hi-hi-1} 复杂度O(N) 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 8 //variable/

2016.7.12 NOIP2013提高组 day2解题报告(未完成版)

考试马不停蹄地到来,昨天的程序还没改完,今天又考了day2,虽然没有昨天那么懵逼,但还是不尽如人意,现在还没讲题,我打算先自己看一次解题报告,争取加深理解,毕竟一位前辈说过,做一套题的质量取决于题本身的质量和你思考的程度. 考试总结: 1.数据分析推测可行算法很重要,要灵活掌握常用算法的时间复杂度: 2.对拍的方式要熟练,写对拍耗费的时间过多: 3.要加强代码实现的能力,比较突出的表现就是写200-300行多函数模拟或搜索的能力: 4.不要急于写过不完的程序,要多拿一点时间来分析数据,样例不够还

【未完成0.0】Noip2012提高组day2 解题报告

第一次写一套题的解题报告,感觉会比较长.(更新中Loading....):) 题目: 第一题:同余方程 描述 求关于x的同余方程ax ≡ 1 (mod b)的最小正整数解. 格式 输入格式 输入只有一行,包含两个正整数a, b,用一个空格隔开. 输出格式 输出只有一行,包含一个正整数x0,即最小正整数解.输入数据保证一定有解. 样例1 样例输入1 3 10 样例输出1 7 限制 每个测试点1s 提示 对于40%的数据,2 ≤b≤ 1,000: 对于60%的数据,2 ≤b≤ 50,000,000:

NOIp2016 Day1&amp;Day2 解题报告

Day1 T1 toy 本题考查你会不会编程. //toy //by Cydiater //2016.11.19 #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <queue> #include <map> #in

noip2011提高组day1+day2解题报告

Day1 T1铺地毯https://www.luogu.org/problem/show?pid=1003 [题目分析] 全部读入以后从最后一个往前找,找到一个矩形的范围覆盖了这个点,那这个矩形就是最上面的地毯,输出即可 #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=10010; int a[maxn],b[maxn],g[maxn],k

CH Round #55 - Streaming #6 (NOIP模拟赛day2)解题报告

T1九九归一 描述 萌蛋在练习模n意义下的乘法时发现,总有一些数,在自乘若干次以后,会变成1.例如n=7,那么5×5 mod 7=4,4×5 mod 7=6,6×5 mod 7=2,2×5 mod 7=3,3×5 mod 7=1.如果继续乘下去,就会陷入循环当中.萌蛋还发现,这个循环的长度经常会是φ(n),即小于n且与n互质的正整数的个数.例如,φ(7)=6,而上述循环的长度也是6,因为5,4,6,2,3,1共有6个数.再如n=6,那么5×5 mod 6=1.这个循环的长度很短,只有2,而恰好φ

NOIp 2011 Day2 解题报告

1.计算系数 本人比较耿直,没有想到递推的组合数公式,而是用了快速幂求逆元. 复杂度O(Klog10007) 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 8 //variable// 9 int a,b,k,n,m,mod=10007; 10

NOIP2015 解题报告

过了这么久才来发解题报告,蒟蒻实在惭愧 /w\ Day1 T1 [思路] 模拟 [代码] 1 #include<iostream> 2 #include<cstring> 3 #include<queue> 4 #include<cmath> 5 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 6 using namespace std; 7 8 const int maxn = 50; 9 10 int G[