uva 1471 defence lines——yhx

来源:互联网 发布:soap报文转换成json 编辑:程序博客网 时间:2024/05/02 00:28
After the last war devastated your country, you - as the king of the land of Ardenia - decided it was
high time to improve the defense of your capital city. A part of your forti cation is a line of mage
towers, starting near the city and continuing to the northern woods. Your advisors determined that the
quality of the defense depended only on one factor: the length of a longest contiguous tower sequence
of increasing heights. (They gave you a lengthy explanation, but the only thing you understood was
that it had something to do with ring energy bolts at enemy forces).
After some hard negotiations, it appeared that building new towers is out of question. Mages of
Ardenia have agreed to demolish some of their towers, though. You may demolish arbitrary number of
towers, but the mages enforced one condition: these towers have to be consecutive.
For example, if the heights of towers were, respectively, 5, 3, 4, 9, 2, 8, 6, 7, 1, then by demolishing
towers of heights 9, 2, and 8, the longest increasing sequence of consecutive towers is 3, 4, 6, 7.
Input
The input contains several test cases. The rst line of the input contains a positive integer Z  25,
denoting the number of test cases. Then Z test cases follow, each conforming to the format described
below.
The input instance consists of two lines. The rst one contains one positive integer n  2  105
denoting the number of towers. The second line contains n positive integers not larger than 109
separated by single spaces being the heights of the towers.
Output
For each test case, your program has to write an output conforming to the format described below.
You should output one line containing the length of a longest increasing sequence of consecutive
towers, achievable by demolishing some consecutive towers or no tower at all.

 1 #include<cstdio> 2 #include<set> 3 #include<cstring> 4 #define M(a) memset(a,0,sizeof(a)) 5 using namespace std; 6 struct ele 7 { 8     int a,g; 9     bool operator < (const ele & x) const10     {11         return a<x.a;12     }13 }e1,e2;14 set<ele> s;15 set<ele>::iterator it;16 int a[200010],f[200010],g[200010];17 int main()18 {19     int i,j,k,m,n,p,q,x,y,z,t,ans;20     bool b;21     scanf("%d",&t);22     while (t--)23     {24         M(a);25         M(f);26         M(g);27         s.clear();28         scanf("%d",&n);29         for (i=1;i<=n;i++)30           scanf("%d",&a[i]);31         for (i=n;i>=1;i--)32           if (a[i]<a[i+1]) f[i]=f[i+1]+1;33           else f[i]=1;34         for (i=1;i<=n;i++)35           if (a[i]>a[i-1]) g[i]=g[i-1]+1;36           else g[i]=1;37         e1.a=a[1];38         e1.g=g[1];39         s.insert(e1);40         ans=1;41         for (i=2;i<=n;i++)42         {43             e1.a=a[i];44             e1.g=g[i];45             it=s.lower_bound(e1);46             b=1;47             if (it!=s.begin())48             {49                 e2=*(--it);50                 if (f[i]+e2.g>ans) ans=f[i]+e2.g;51                 if (e1.g<=e2.g) b=0;52             }53             if (b)54             {55                 s.erase(e1);56                 s.insert(e1);57                 it=s.find(e1);58                 it++;59                 while (it!=s.end()&&(*it).a>e1.a&&(*it).g<=e1.g) s.erase(it++);60             }61         }62         printf("%d\n",ans);63     }64 }

因为不太会写stl,所以照着标程边抄边改边理解。

对于每个元素求出以它开头和结尾的最长递增子序列长度f[i]和g[i],那么对于每一个确定的后端点i,只需要找到满足a[j]<a[i]的最大g[j]即可。

易知如果a[j']>a[j]且g[j']<=g[j],则j’一定没用,因为j不但比他容易用,还比他效果好。

用set存储所有满足条件的pair<a[j],g[j]>,按a排序【则g也一定有序】。对于每个i,用lower_bound找到第一个>=它的,也就找到了最后一个<它的。用其更新答案。

用i更新完ans之后,需要把i也插入set中,为后面的元素服务。先判断i是否要插入(也就是有没有比他好的,只需要和刚才找见的最后一个<它的比较即可),再看插入之后可以删掉哪些元素(也就是没有它好的,向他前面一个一个找)。

0 0
原创粉丝点击