期望得分:22+100+22=144
实际得分:22+86+22=130
出题人有卡常嫌疑?(自信点,把问号去掉)
开题顺序3 1 2,T3一眼不可做,打上\(O(n^4)\)的暴力
然后T1发现状压可22pts,打上状压
然后觉得T1可做,根据之前的经验,决定先从T3骗点分再回来想T1正解
然后发现T3这个方程有点水,想出正解思路后,由于存在正解码错爆0的案例,就一直手模数据,T1就放下了
比赛结束最后看题解,发现T1竟是最可做的,,,
要给觉得可做的题多留些思考时间,提高效率,心态放平
T1
将n个物品划分为\(O(2^n)\)个集合,每个集合看做是一个一次函数
所有的一次函数的最大值,在坐标系上 单增 或 单减 或 先减后增
对于对于单减和先减后增的减,用0特判
剩下的情况具有单调性,二分就行了
T2
树上的每个点的x值可以转化成\(x_i=x_1+k\)或\(x_i=-x_1+k\) ,与深度有关
回答每次询问时,若两个的\(x_1\)的符号相反,判断\(k_i+k_j\)与\(w\)的关系。
若相同,判个整数,直接解出来
然后若一个节点的\(w\)改变,只对它的子树有影响,维护\(dfs\)序区间修改,单点查询
线段树被卡,用树状数组维护差分数组就行了
T3
正解还不会,\(O(n^4)\)的暴力就枚举每个矩形的上下左右边界的点,然后打标记去个重就22pts了
冥冥中想起一句话,记得取模
代码
T1
#include<bits/stdc++.h> using namespace std; #define int long long const int N=1000011; struct pot_{ int k,b; }pot[N]; int n,m,s; int ans1[N]; priority_queue<int> dui; inline int read() { int ss=0,w=1; char ch=getchar(); while(ch>'9'||ch<'0') { if(ch=='-') w=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { ss=(ss<<1)+(ss<<3)+(ch^48); ch=getchar(); } return ss*w; } bool cmp(int a,int b) { return a>b; } bool check(int x) { for(int i=0;i<n;i++) ans1[i]=pot[i+1].k*x+pot[i+1].b; nth_element(ans1,ans1+m,ans1+n,cmp); int ans=0; for(int i=0;i<m;i++) { if(ans1[i]<0) continue; ans+=ans1[i]; if(ans>=s) return 1; } return 0; } signed main() { int ans2=0; n=read(); m=read(); s=read(); for(int i=1;i<=n;i++) { pot[i].k=read(); pot[i].b=read(); dui.push(pot[i].b); } for(int i=1;i<=m;i++) { if(dui.top()<0) break; ans2+=dui.top(); dui.pop(); } if(ans2>=s) { cout<<0<<endl; return 0; } int l=1,mid,r=1e9,ans=0x7ffffffffffffff; while(l<=r) { mid=(l+r)>>1; if(check(mid)) { ans=mid; r=mid-1; } else l=mid+1; } cout<<ans<<endl; return 0; }
T2
#include<bits/stdc++.h> using namespace std; const int N=1000011; struct qxxx{ int v,next; }cc[2*N]; int n,q; int dep[N],size[N]; int dfn[N],rle[N],st; int first[N],cnt; long long w[N],sum[N]; long long cs1[N],cs2[N]; long long cf1[N],cf2[N]; inline int read() { int s=0,w=1; char ch=getchar(); while(ch>'9'||ch<'0') { if(ch=='-') w=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { s=(s<<1)+(s<<3)+(ch^48); ch=getchar(); } return s*w; } void qxx(int u,int v) { cc[++cnt].v=v; cc[cnt].next=first[u]; first[u]=cnt; return; } int lowbit(int x) { return x&(-x); } void insert1(int x,long long val) { while(x<=n) { cf1[x]+=val; x+=lowbit(x); } return; } void insert2(int x,long long val) { while(x<=n) { cf2[x]+=val; x+=lowbit(x); } return; } long long ask1(int x) { long long sum=0; while(x) { sum+=cf1[x]; x-=lowbit(x); } return sum; } long long ask2(int x) { long long sum=0; while(x) { sum+=cf2[x]; x-=lowbit(x); } return sum; } void dfs(int x) { dfn[x]=++st; rle[st]=x; size[x]=1; for(int i=first[x];i;i=cc[i].next) { dep[cc[i].v]=dep[x]+1; sum[cc[i].v]=-sum[x]+w[cc[i].v]; dfs(cc[i].v); if(dep[cc[i].v]&1) cs1[dfn[cc[i].v]]=sum[cc[i].v]; else cs2[dfn[cc[i].v]]=sum[cc[i].v]; size[x]+=size[cc[i].v]; } return; } void pre() { for(int i=1;i<=n;i++) { insert1(i,cs1[i]-cs1[i-1]); insert2(i,cs2[i]-cs2[i-1]); } return; } int main() { int jd; int x,y,z; n=read(); q=read(); for(int i=2;i<=n;i++) { qxx(read(),i); w[i]=read(); } dep[1]=1; dfs(1); pre(); for(int i=1;i<=q;i++) { jd=read(); if(jd==1) { x=read(); y=read(); z=read(); long long xa,ya; long long sgx,sgy; if(dep[x]&1) { sgx=1; xa=ask1(dfn[x]); } else { sgx=-1; xa=ask2(dfn[x]); } if(dep[y]&1) { sgy=1; ya=ask1(dfn[y]); } else { sgy=-1; ya=ask2(dfn[y]); } if(sgx+sgy==0) { if(xa+ya==z) printf("%s\n","inf"); else printf("%s\n","none"); } else { long long fz=z-xa-ya; long long fm=sgx+sgy; if(fz%fm) printf("%s\n","none"); else printf("%lld\n",fz/fm); } } else { x=read(); y=read(); long long val=y-w[x]; if(!(dep[x]&1)) val*=-1; insert1(dfn[x],val); insert1(dfn[x]+size[x],-val); insert2(dfn[x],-val); insert2(dfn[x]+size[x],val); w[x]=y; } } return 0; }