1005传送门
题意:一个二维图上有若干个点,每个点有一个坐标值(xi,yi),以及一个价值(vi) ( -1e9<=xi,yi,vi<=1e9),求一个价值和最大的矩形(只需输出最大价值和)
题解:离散化后枚举上下边界可以将二维图降维为一个求一维动态最大字段和的问题,在横轴上建立线段树即可维护最大字段和
#include
using namespace std;
#define debug(x) cout<<#x<<" is "<g[maxn];
int xx[maxn],yy[maxn];
void build(int rt,int l,int r){
nod[rt].l=l;
nod[rt].r=r;
nod[rt].sum=nod[rt].maxxnxt=nod[rt].maxxpre=nod[rt].maxxval=0;
if(l==r){
return;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build((rt<<1)|1,mid+1,r);
}
void pushup(int rt){
nod[rt].maxxpre=max(nod[rt<<1].maxxpre,nod[rt<<1].sum+nod[(rt<<1)|1].maxxpre);
nod[rt].maxxnxt=max(nod[(rt<<1)|1].maxxnxt,nod[rt<<1].maxxnxt+nod[(rt<<1)|1].sum);
nod[rt].maxxval=max(max(nod[rt<<1].maxxval,nod[(rt<<1)|1].maxxval),max(max(nod[rt<<1].maxxnxt,nod[(rt<<1)|1].maxxpre),nod[rt<<1].maxxnxt+nod[(rt<<1)|1].maxxpre));
nod[rt].sum=nod[rt<<1].sum+nod[(rt<<1)|1].sum;
}
void update(int rt,int l,int r,int x,ll val){
if(l==r){
nod[rt].sum+=val;
nod[rt].maxxval+=val;
nod[rt].maxxnxt+=val;
nod[rt].maxxpre+=val;
return ;
}
int mid=(l+r)>>1;
if(mid>=x)update(rt<<1,l,mid,x,val);
else update((rt<<1)|1,mid+1,r,x,val);
pushup(rt);
}
ll query(int rt){
return max(max(nod[rt].maxxval,nod[rt].maxxpre),nod[rt].maxxnxt);
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){g[i].clear();scanf("%d%d%lld",&p[i].x,&p[i].y,&p[i].val);xx[i]=p[i].x,yy[i]=p[i].y;}
sort(xx+1,xx+1+n);
sort(yy+1,yy+1+n);
int siz1=unique(xx+1,xx+1+n)-(xx+1);
int siz2=unique(yy+1,yy+1+n)-(yy+1);
for(int i=1;i<=n;i++){
p[i].x=lower_bound(xx+1,xx+1+siz1,p[i].x)-xx;
p[i].y=lower_bound(yy+1,yy+1+siz2,p[i].y)-yy;
struct pot2 aa;
aa.x=p[i].x;
aa.val=p[i].val;
g[p[i].y].push_back(aa);
}
ll ans=0;
for(int i=1;i<=siz2;i++){
build(1,1,siz1);
for(int j=i;j<=siz2;j++){
for(int k=0;k
1008传送门
题意:定义f(n,m)为大于n的第m个与n互质的数,令k=(f(n,m)-n)^n,现在已知k和m的值,输出最小的满足要求的n或者-1(不存在)(k<=1e18,m<=100)
题解:由于k巨大而m很小,并且由m最大为100可以知道f(n,m)-n一定不太大(打表也可以发现f(n,m)-n始终<2^10),所以可以直接枚举(f(n,m)-n)的值,并且利用k的二进制下的各个值来计算n,检查枚举出的n的f(n,m)是否满足要求。总复杂度应为O(2^10 * 2^10)
#include
using namespace std;
//#define debug(x) cout<<#x<<" is "<m)return 0;
}
if(t1>(pos-1))&1){
if(dfs(pos-1,sum1+(1<<(pos-1)),sum2))return 1;
return dfs(pos-1,sum1,sum2+(1<<(pos-1)));
}
else{
if(dfs(pos-1,sum1,sum2))return 1;
return dfs(pos-1,sum1+(1<<(pos-1)),sum2+(1<<(pos-1)));
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%lld%lld",&k,&m);
ll x=k;
ll t1=0;
ll ac=0;
while(x){
t1++;
if(t1>9&&(x%2)){
ac+=(1ll<<(t1-1));
}
x/=2;
}
if(dfs(9ll,0ll,ac)){
;
}
else{
printf("-1\n");
}
}
return 0;
}
1012传送门
题意:给出一个小顶堆,两人轮流从叶子处取数同时删除取走的叶子,求二者都最优情况下分别得到的总和
题解:大顶堆优先队列
#include
using namespace std;
//#define debug(x) cout<<#x<<" is "<pq;
int main(){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
ll s1=0;
ll s2=0;
for(int i=1;i<=n;i++){ll a;scanf("%lld",&a);pq.push(a);}
for(int i=1;i<=n;i++){
ll xx=pq.top();pq.pop();
if(i%2)s1+=xx;
else s2+=xx;
}
printf("%lld %lld\n",s1,s2);
}
return 0;
}