http://icpc.njust.edu.cn/Contest/6258/I/
Tree DP 读题
Code:
#include <bits/stdc++.h>
using namespace std;
int n,x,y;
vector<int>g[50008];
int dp[50008][2];
int v[50008];
int tag[50008];
int ans=0;
void dfs(int u,int flag){
//cout<<u<<endl;
flag^=tag[u];
if(flag)v[u]=-v[u];
if(u==0){
for(int i=0;i<g[u].size();i++){
dfs(g[u][i],flag);
ans+=dp[g[u][i]][0];
}
return ;
}
else {
int c=x;
if(tag[u])c=y;
int s00=v[u],s01=-v[u]-c;
int s10=-v[u],s11=v[u]-c;
for(int i=0;i<g[u].size();i++){
dfs(g[u][i],flag);
int to=g[u][i];
s00+=dp[to][0];
s01+=dp[to][1];
s10+=dp[to][1];
s11+=dp[to][0];
}
dp[u][0]=max(s00,s01);
dp[u][1]=max(s10,s11);
}
}
int main(){
while(~scanf("%d%d%d",&n,&x,&y)){
for(int i=1;i<=n;i++){
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
v[i]=a;
if(d)v[i]=-v[i];
g[b].push_back(i);
tag[i]=c;
}
ans=0;
dfs(0,0);
if(ans<0)printf("HAHAHAOMG\n");
else printf("%d\n",ans);
for(int i=0;i<=n;i++)g[i].clear();
}
}
http://icpc.njust.edu.cn/Contest/6263/I/
三维偏序 CDQ分治
Code:
#include <bits/stdc++.h>
using namespace std;
int n,m;
map<int,int>ma;
map<int,int>tim;
struct node{
int a,b,c,v,id;
}rec[100003],tmp[100003],b[100003];
int ans[100003];
int v[100003];
int tot,ttot;
bool cmp1(node a,node b){
if(a.a!=b.a)return a.a>b.a;
if(a.b!=b.b)return a.b>b.b;
return a.c>b.c;
}
bool cmp2(node a,node b){
if(a.b!=b.b)return a.b>b.b;
return a.c>b.c;
}
void debug(){
for(int i=1;i<=tot;i++){
for(int j=1;j<=tot;j++){
if(j==i)continue;
if(rec[j].a>=rec[i].a&&rec[j].b>=rec[i].b&&rec[j].c>=rec[i].c)ans[rec[i].id]++;
}
}
}
int c[100003];
int lowbit(int x){
return x&(-x);
}
int query(int x){
int ret=0;
while(x<=100000){
ret+=c[x];
x+=lowbit(x);
}
return ret;
}
void update(int x){
while(x){
c[x]++;
x-=lowbit(x);
}
}
void reset(int p){
while(p){
c[p]=0;
p-=lowbit(p);
}
}
void cdq(int l, int r){
if(l==r)return;
int m=(l+r)/2;
cdq(l, m);
cdq(m+1, r);
for(int i=l;i<=r;i++){
b[i]=rec[i];
}
sort(b+l, b+m+1, cmp2);
sort(b+m+1, b+r+1, cmp2);
int j=l;
for(int i=m+1;i<=r;i++){
while(j<=m&&b[j].b>=b[i].b){
update(b[j++].c);
}
ans[b[i].id]+=query(b[i].c);
}
for(int i=l;i<=m;i++)reset(b[i].c);
return;
}
int main(){
int T;
scanf("%d",&T);
for(int tt=1;tt<=T;tt++){
memset(ans,0,sizeof(ans));
memset(c,0,sizeof(c));
scanf("%d%d",&n,&m);
ma.clear();
tim.clear();
for(int i=1;i<=n;i++){
int a,b;
scanf("%d%d",&a,&b);
if(ma.find(b)==ma.end()||ma[b]<a){
ma[b]=a;
tim[b]=1;
}
else if(ma[b]==a){
tim[b]++;
}
}
tot=0,ttot=0;
for(int i=1;i<=m;i++){
int c,d,e;
scanf("%d%d%d",&c,&d,&e);
if(ma.find(e)==ma.end())continue;
++ttot;
tmp[ttot].a=c;
tmp[ttot].b=d;
tmp[ttot].c=ma[e];
tmp[ttot].v=tim[e];
tmp[ttot].id=tot;
}
sort(tmp+1,tmp+1+ttot,cmp1);
for(int i=1;i<=ttot;i++){
if(tot&&tmp[i].a==rec[tot].a&&tmp[i].b==rec[tot].b&&tmp[i].c==rec[tot].c)rec[tot].v+=tmp[i].v;
else {
++tot;
rec[tot]=tmp[i];
rec[tot].id=tot;
}
}
for(int i=1;i<=tot;i++){
v[i]=rec[i].v;
}
sort(rec+1,rec+1+tot,cmp1);
cdq(1,tot);
int ret=0;
for(int i=1;i<=tot;i++){
if(!ans[i]){
ret+=v[i];
}
}
printf("Case #%d: %d\n",tt,ret);
}
}
http://icpc.njust.edu.cn/Contest/6263/K/
Mask DP
Code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll a[6];
ll dp[20005][35][6];
ll fac[20005];
ll fav[20005];
ll power(ll n,ll p){
ll ans=1;
ll base=n;
while(p){
if(p&1){
ans=ans*base%mod;
}
base=base*base%mod;
p>>=1;
}
return ans;
}
ll inv(ll x){
return power(x,mod-2);
}
ll C(ll x,ll y){
if(y==0)return 1;
return (fac[x]*fav[y]%mod)*fav[x-y]%mod;
}
ll cnt(ll x){
return __builtin_popcount(x);
}
void debug(){
ll x,y;
while(cin>>x>>y){
cout<<C(x,y)<<endl;
}
}
int main(){
fac[0]=1;
fav[0]=1;
for(ll i=1;i<=20000;i++){
fac[i]=fac[i-1]*i%mod;
fav[i]=inv(fac[i]);
}
ll T;
scanf("%lld",&T);
for(ll tt=1;tt<=T;tt++){
ll n;
scanf("%lld",&n);
for(ll i=0;i<5;i++){
scanf("%lld",&a[i]);
}
memset(dp,0,sizeof(dp));
for(ll k=1;k<=5;k++){
dp[0][0][k]=1;
for(ll i=1;i<=n;i++){
for(ll j=0;j<32;j++){
dp[i][j][k]+=dp[i-1][j][k]*(5-k+cnt(j));
dp[i][j][k]%=mod;
for(ll l=0;l<5;l++){
if(j&(1<<l)){
if(i-a[l]-1<0)continue;
dp[i][j][k]+=dp[i-a[l]-1][j^(1<<l)][k]*C(i-1,a[l]);
dp[i][j][k]%=mod;
}
}
}
}
}
ll ans1=power(5,n);
for(ll k=1;k<=5;k++){
ll op=1;
if(k%2)op=-1;
for(ll j=0;j<32;j++){
if(cnt(j)==k){
ans1+=(op*dp[n][j][k]+mod);
ans1%=mod;
}
}
}
ll ans2;
if(a[0]==0){
ans2=0;
}
else {
n--;
a[0]--;
memset(dp,0,sizeof(dp));
for(ll k=1;k<=5;k++){
dp[0][0][k]=1;
for(ll i=1;i<=n;i++){
for(ll j=0;j<32;j++){
dp[i][j][k]+=dp[i-1][j][k]*(5-k+cnt(j));
dp[i][j][k]%=mod;
for(ll l=0;l<5;l++){
if(j&(1<<l)){
if(i-a[l]-1<0)continue;
dp[i][j][k]+=dp[i-a[l]-1][j^(1<<l)][k]*C(i-1,a[l]);
dp[i][j][k]%=mod;
}
}
}
}
}
ans2=power(5,n);
for(ll k=1;k<=5;k++){
ll op=1;
if(k%2)op=-1;
for(ll j=0;j<32;j++){
if(cnt(j)==k){
ans2+=(op*dp[n][j][k]+mod);
ans2%=mod;
}
}
}
}
ans1=(ans1-ans2+mod)%mod;
printf("Case #%d: %lld\n",tt,ans1);
}
}
http://icpc.njust.edu.cn/Contest/6265/D/
Tree DP DSU启发式合并
#include <bits/stdc++.h>
using namespace std;
const int inf=1e9+7;
struct node{
int p,v;
};
bool operator<(const node& a,const node& b){
return a.p<b.p;
}
multiset<node>g[100003];
int n,m;
int bar[100003];
int mi[100003];
int ma[100003];
int id[100003];
int dp[100003];
int sum[100003];
int f[100003];
bool cmp(int x,int y){
return bar[x]<bar[y];
}
int getfa(int u){
if(f[u]==u)return u;
return f[u]=getfa(f[u]);
}
void Union(int u,int v){
u=getfa(u);
v=getfa(v);
if(g[u].size()<g[v].size())swap(u,v);
int tma=max(ma[u],ma[v]);
int tmi=min(ma[u],ma[v]);
ma[u]=tma;
mi[u]=tmi;
sum[u]+=sum[v];
dp[u]=max(dp[u]+dp[v],sum[u]);
for(auto it=g[v].begin();it!=g[v].end();it++){
g[u].insert(*it);
}
auto it=g[u].upper_bound((node){mi[v],0});
for(;it!=g[u].end();it++){
if((it->p)>mi[u])break;
sum[u]+=it->v;
dp[u]=max(dp[u],sum[u]);
}
f[v]=u;
}
int main(){
int T;
cin>>T;
for(int tt=1;tt<=T;tt++){
cin>>n>>m;
bar[0]=inf;
bar[n]=inf;
for(int i=1;i<n;i++){
scanf("%d",&bar[i]);
id[i]=i;
}
for(int i=1;i<=n;i++){
f[i]=i;
mi[i]=min(bar[i-1],bar[i]);
ma[i]=max(bar[i-1],bar[i]);
}
sort(id+1,id+n,cmp);
for(int i=1;i<=m;i++){
int id,p,v;
scanf("%d%d%d",&id,&p,&v);
p++;
if(v==0){
v--;
}
g[id].insert((node){p,v});
}
for(int i=1;i<=n;i++){
sum[i]=0;
for(auto it=g[i].begin();it!=g[i].end();it++){
sum[i]+=(it->v==-1);
}
auto it=g[i].begin();
dp[i]=sum[i];
for(;it!=g[i].end();it++){
if((it->p)>mi[i])break;
sum[i]+=it->v;
dp[i]=max(dp[i],sum[i]);
}
}
for(int i=1;i<n;i++){
int l=id[i];
int r=l+1;
Union(l,r);
}
int rt=getfa(1);
for(int i=1;i<=n;i++)g[i].clear();
printf("Case #%d: %d\n",tt,dp[rt]);
}
}