icpc的老题了,最近学校oj调出来拿来在训练赛做了,比赛的时候跟队友讨论了两种做法,一种是for循环加树状数组(分析了分析时间复杂度感觉虽然会t,但是应该不存在那种故意卡的数据,就直接交了,没想到一下就过了,于是第二种做法就没有实践),然而没想到比赛刚一结束学长反手就交了这样的一组hack数据卡掉了,QWQ。
//#pragma GCC optimize(4)
#include <bits/stdc++.h>
#define rint register int
typedef long long ll;
using namespace std;
const int N=100000+5;
int a[N],b[N],c[N],vis[N],n,m;
struct node
{
int x,y,z;
}ar[N];
void add(int x,int val)
{
for(int i=x;i<=n;i+=i&-i)c[i]+=val;
}
int ask(int x)
{
int ans=0;
for(int i=x;i;i-=i&-i) ans+=c[i];
return ans;
}
bool cmp(node s,node t)
{
return s.y<t.y;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]!=0)
{
vis[i]=1;
add(i,a[i]);
}
else
{
add(i,-1);
a[i]=-1;
}
}
for(int i=1;i<=m;i++)
{
cin>>ar[i].x>>ar[i].y>>ar[i].z;
}
sort(ar+1,ar+1+m,cmp);
int flag=0;
for(int i=1;i<=m;i++)
{
int l=ar[i].x,r=ar[i].y;
int sum=ask(r)-ask(l-1);
for(int j=r;j>=l&&sum<ar[i].z;j--)
{
if(!vis[j])
{
sum+=2;
add(j,2);
vis[j]=1;
a[j]=1;
}
}
if(sum<ar[i].z)
{
flag=1;break;
}
}
if(flag) printf("Impossible
");
else
{
for(int i=1;i<n;i++)
{
printf("%d ",a[i]);
}
printf("%d
",a[n]);
}
return 0;
}
/**************************************************************
Problem: 11753
User: Qianwan063
Language: C++
Result: 时间超限
****************************************************************/
另一种做法是借助了并查集,f[i]指向第一个可以变成1的位置,其他实现原理同上
#pragma GCC optimize(4)
#include <bits/stdc++.h>
#define rint register int
typedef long long ll;
using namespace std;
const int N=100000+5;
int a[N],b[N],c[N],n,m,f[N];
int getf(int x)
{
if(f[x]==x) return x;
return f[x]=getf(f[x]);
// return f[x]==x? x:f[x]=getf(f[x]);
}
struct node
{
int x,y,z;
}ar[N];
void add(int x,int val)
{
for(int i=x;i<=n;i+=i&-i)c[i]+=val;
}
int ask(int x)
{
int ans=0;
for(int i=x;i;i-=i&-i) ans+=c[i];
return ans;
}
bool cmp(node s,node t)
{
return s.y<t.y;
}
int main()
{
//freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++) f[i]=i;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]!=0)
{
int x=getf(i);
int y=getf(i-1);
f[x]=y;
add(i,a[i]);
}
else
{
add(i,-1);
a[i]=-1;
}
}
for(int i=1;i<=m;i++)
{
cin>>ar[i].x>>ar[i].y>>ar[i].z;
}
sort(ar+1,ar+1+m,cmp);
int flag=0;
for(int i=1;i<=m;i++)
{
int l=ar[i].x,r=ar[i].y;
int sum=ask(r)-ask(l-1);
int pos=r;
while(sum<ar[i].z&&(pos=getf(pos))>=l)
{
sum+=2;
add(pos,2);
a[pos]=1;
f[pos]=getf(pos-1);
}
if(sum<ar[i].z)
{
flag=1;break;
}
}
if(flag) printf("Impossible
");
else
{
for(int i=1;i<n;i++)
{
printf("%d ",a[i]);
}
printf("%d
",a[n]);
}
return 0;
}
/**************************************************************
Problem: 11753
User: Qianwan063
Language: C++
Result: 正确
Time:53 ms
Memory:6628 kb
****************************************************************/