直接放题:
儿童节快乐
(happy.cpp)
【描述】
儿童节即将到来。在这一天,小朋友们会得到好多糖果。在MAX城市,人民发明了一种糖果自动管理系统(ACM系统),该系统能管理N堆糖果。系统只能执行两种操作。
(1)I a b c(1≤a≤b≤N,0 < c≤100),ACM将在堆a至堆b之间(包含a和b)每堆糖果加c个。 //改段
(2)C a b(1≤a≤b≤N),ACM将会选择a到b堆之间糖果数最多的那堆糖果送给一个小朋友。如果有两堆或两堆以上糖果数为最大值,选择那么编号小的那堆。 //求点
给出一系列的操作,对于每个C操作,输出堆的糖果数。
【输入】
有多组测试数据。
每组测试数据的第一行为两个整数N,M(0< N,M≤10^5),N表示糖果堆的数目,M表示操作的次数。
下来M行,每行为一个操作。
输入当N=0并且M=0时结束,并且不做任何处理。
初始时,所有堆糖果数目为0。
【输出】
对于每个C操作,输出小朋友能得到的糖果的数目。
【样例输入】
5 4
I 1 5 1
C 2 3
I 2 2 4
C 2 3
0 0
【样例输出】
1
4
#include<cstdio>
#include<cstring>
const int N=100005;
int n,m;
struct qq
{
int l,r;
int s1,s2;
int z,z1;//最大的值 最大是哪一个编号
int lazy;
}s[N*2];
int num;
void bt (int l,int r)
{
num++;
int a=num;
s[a].l=l;s[a].r=r;
s[a].s1=s[a].s2=-1;
s[a].z=0;
s[a].z1=l;
s[a].lazy=0;
if (l==r) return ;
int mid=(l+r)/2;
s[a].s1=num+1;bt(l,mid);
s[a].s2=num+1;bt(mid+1,r);
return ;
}
void add (int now,int l,int r,int c)
{
//printf("%d %d z:%d lazy:%d\n",s[now].l,s[now].r,s[now].z,s[now].lazy);
if (s[now].l==s[now].r)
{
// printf("YES:%d %d\n",l,r);
s[now].z+=c;
return ;
}
if (s[now].l==l&&s[now].r==r)
{
s[now].lazy+=c;
s[now].z+=c;
return ;
}
int s1=s[now].s1,s2=s[now].s2;
s[s1].lazy+=s[now].lazy;
s[s1].z+=s[now].lazy;
s[s2].lazy+=s[now].lazy;
s[s2].z+=s[now].lazy;
s[now].lazy=0;
int mid=(s[now].l+s[now].r)/2;
if (r<=mid) add(s1,l,r,c);
else if (l>mid) add(s2,l,r,c);
else
{
add(s1,l,mid,c);
add(s2,mid+1,r,c);
}
if (s[s1].z>=s[s2].z)
{
s[now].z=s[s1].z;
s[now].z1=s[s1].z1;
}
else
{
s[now].z=s[s2].z;
s[now].z1=s[s2].z1;
}
return ;
}
int z,z1;
void find (int now,int l,int r)
{
if (s[now].l==l&&s[now].r==r)
{
z=s[now].z;
z1=s[now].z1;
return ;
}
int s1=s[now].s1,s2=s[now].s2;
s[s1].lazy+=s[now].lazy;
s[s1].z+=s[now].lazy;
s[s2].lazy+=s[now].lazy;
s[s2].z+=s[now].lazy;
s[now].lazy=0;
int mid=(s[now].l+s[now].r)/2;
if (r<=mid) find (s1,l,r);
else if (l>mid) find (s2,l,r);
else
{
find(s1,l,mid);
int a=z,a1=z1;
find(s2,mid+1,r);
if (a>=z)
{
z=a;
z1=a1;
}
}
return ;
}
int main()
{
freopen("happy.in","r",stdin);
freopen("happy.out","w",stdout);
while (scanf("%d%d",&n,&m))
{
if (n==0&&m==0) break;
num=0;bt(1,n);
for (int u=1;u<=m;u++)
{
//for (int u=1;u<=num;u++) printf("%d %d %d %d z:%d z1:%d lazy:%d\n",s[u].l,s[u].r,s[u].s1,s[u].s2,s[u].z,s[u].z1,s[u].lazy);
char ss[5];
scanf("%s",ss);
if (ss[0]=='I')
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(1,a,b,c);
}
else
{
int a,b;
scanf("%d%d",&a,&b);
find (1,a,b);
printf("%d\n",z);
/*for (int u=1;u<=num;u++) printf("%d %d %d %d z:%d z1:%d lazy:%d\n",s[u].l,s[u].r,s[u].s1,s[u].s2,s[u].z,s[u].z1,s[u].lazy);
printf("\n");*/
add(1,z1,z1,-z);
}
}
}
return 0;
}
//很不好意思我遇到了一个很懒的出题老师:-)
儿童节快乐2
(happy2.cpp)
【问题描述】
儿童节又来了。在这一天,小朋友们会得到好多糖果。在MAX城市,人民更新新型的糖果自动管理系统(ACM2系统),该系统能管理N*N堆糖果。系统只能执行两种操作。
(1)I a b c d e(1≤a≤c≤N,1≤b≤d≤N,0 < e≤100),ACM2将在矩阵【a,b】-【c,d】之间的每堆糖果加e个。
(2)C a b c d(1≤a≤c≤N,1≤b≤d≤N),ACM2将会选择矩阵【a,b】-【c,d】之间糖果数最多的那堆糖果送给一个小朋友。如果有两堆或两堆以上糖果数为最大值,先按行再按列选择编号小的那堆。
给出一系列的操作,对于每个C操作,输出堆的糖果数。
【输入描述】
第一行为两个整数N,M(0< N,M≤2000),N*N表示糖果堆的数目,M表示操作的次数。
接下来M行,每行为一个操作。
初始时,所有堆糖果数目为0。
【输出描述】
对于每个C操作,输出小朋友能得到的糖果的数目。
【输入样例】
3 4
I 1 1 3 3 1
C 2 2 3 3
I 2 1 3 2 2
C 1 1 3 3
【输出样例】
1
3
升级版将一维改成了二维
不要被迷惑了
数据范围比较小。暴力比树状数组/线段树还要快。
所以在比赛时的无上真理:
能打暴力,就打暴力
暴力万岁!
如果有同学不服可以用树状数组做
我并不介意被打脸
我脸皮厚嘛:-)
//happy暴力
#include<cstdio>
#include<cstdlib>
#include<cstring>
int n,m;
int p[2010][2010];
int main()
{
freopen("happy2.in","r",stdin);
freopen("happy2.out","w",stdout);
scanf("%d %d",&n,&m);
memset(p,0,sizeof(p));
for (int i=1;i<=m;i++)
{
char op[10];
int a,b,c,d,e;
scanf("%s",op);
if (op[0]=='I')
{
scanf("%d %d %d %d %d",&a,&b,&c,&d,&e);
for (int x=a;x<=c;x++)
for (int y=b;y<=d;y++)
p[x][y]+=e;
}
if (op[0]=='C')
{
scanf("%d %d %d %d",&a,&b,&c,&d);
int xx=a,yy=b,max=0;
for (int x=a;x<=c;x++)
for (int y=b;y<=d;y++)
{
if (p[x][y]>max)
{
max=p[x][y];
xx=x;yy=y;
}
}
printf("%d\n",max);
p[xx][yy]=0;
}
}
return 0;
}